missive / emoji-mart

🏪 One component to pick them all
https://missiveapp.com/open/emoji-mart
MIT License
8.38k stars 802 forks source link

Updating locale property with custom categories causes an error #794

Open sjsanc opened 1 year ago

sjsanc commented 1 year ago

Changing the locale prop with custom emojis loaded triggers the below error after an interaction. Removing the custom property prevents this issue, so I'm assuming it's failing to load the custom category after a reload. It doesn't happen with all locales; for example, setting it to English after a reload never breaks.

Picker.tsx:893 Uncaught (in promise) TypeError: Cannot destructure property 'root' of 'this.refs.categories.get(...)' as it is undefined.
    at Picker.tsx:893:1
    at Array.map (<anonymous>)
    at $89bd6bb200cc8fef$export$2e2bcd8739ae039.renderCategories (Picker.tsx:892:1)
    at $89bd6bb200cc8fef$export$2e2bcd8739ae039.render (Picker.tsx:1119:1)
    at $fb96b826c0c5f37a$var$j (index.js:171:1)
    at component.js:221:1
    at Array.some (<anonymous>)
    at $fb96b826c0c5f37a$var$g (component.js:216:1)
(anonymous) @ Picker.tsx:893
...

The component itself:

    <Picker
      data={data}
      custom={[customGithubEmojis]}
      categoryIcons={customEmojiCategories}
      onEmojiSelect={onEmojiSelect}
      theme={mode === "dark" ? "dark" : "light"}
      sx={{ pt: "1", pb: "1" }}
      locale={locale}
    />
rickstaa commented 1 year ago

@sjsanc I could not reproduce your problems when I worked on https://github.com/rickstaa/github-emoji-picker/pull/63. Is this still an error in emoji-mart, or could it be something in our repository?

syusui-s commented 9 months ago

I met the same issue. It doesn't work properly if I specify i18n or custom property.

I'm working on custom emojis for my app.

To reproduce, you can use the code below.

I'm using emoji-mart Picker (PickerElement.tsx) in popup component. It means that Picker is instantiated multiple times and it will be removed when a popup component is closed.

For the first time popup, custom emojis and i18n worked. However, for the next popup, Picker is broken. Only the first few dozen emojis are rendered, the rest are not. The tab of custom emojis are not displayed.

And, I got the following error:

Uncaught (in promise) TypeError: this.refs.categories.get(...) is undefined
    children Picker.tsx:893
    renderCategories Picker.tsx:892
    render Picker.tsx:1121
  const picker = new Picker({
    data: async () => {
      const response = await fetch('https://cdn.jsdelivr.net/npm/@emoji-mart/data');
      return response.json();
    },
    i18n: async () => {
      const response = await fetch('https://cdn.jsdelivr.net/npm/@emoji-mart/data/i18n/ja.json');
      return response.json();
    },
    custom: [
      {
        id: 'custom',
        name: 'Custom Emojis',
        emojis: customEmojis,
      },
    ],
    locale: 'ja',
    onClickOutside: () => picker.remove(),
  });

I confirmed that it works if I remove i18n property or custom property.

I'm not sure this relates to the issue but I heard that the same error happens if custom property is used and there are multiple Picker instances at the same time.

I am using Firefox 118.0b7 on Linux/x86_64.

ertrzyiks commented 5 months ago

I created a sandbox with the bug reproduced in the simplest possible way: https://codesandbox.io/p/sandbox/gallant-benz-5dj4ht?file=%2Fsrc%2FApp.js%3A5%2C40

Screenshot 2024-01-26 at 10 29 55

Looks like it happens because of the Data object is a singleton and that doesn't play nicely with multiple instances of the Picker at the same page.