joeattardi / picmo

JavaScript emoji picker. Any app, any framework.
https://picmojs.com
MIT License
1.19k stars 118 forks source link

Unrecovered IndexDB Error #271

Closed afogel closed 1 year ago

afogel commented 1 year ago

Hey! Thanks for an incredible library. I'm using it in a React application and encountered some surprising behavior. On initial load (when IndexedDB has no PicMo entry), there's an issue loading the emojis. On reload, it tends to work alright, but I was surprised to find that the Try Again button did not successfully reload the emojis when the initial load failed. Here is a video of the bug in action: bug_p1.webm bug_p2.webm

I'm using google chrome in the video, but it also happens in firefox. On a mac.

Stack trace: Promise.then (async)

setEmojiData @ index.js:428   create @ index.js:2441   onError @ index.js:2283   (anonymous) @ index.js:1008   emit @ index.js:1007   (anonymous) @ index.js:2489 |  

setEmojiData(e) {
// in the e.then(), I think
    this.emojiDataPromise = e, e.then((t) => {
      this.emojiData = t;
    });
  }
joeattardi commented 1 year ago

Uh-oh, that doesn't look good. Let me see if I can reproduce this on my end. Maybe it's something specific to React, I can try to create a quick Vite React project and see what happens.

joeattardi commented 1 year ago

I haven't been able to reproduce this issue, could you share the code you are using to integrate with React?

afogel commented 1 year ago

Thanks for looking into this!!! Here's the component I built: the selectionCallback is the set[RESOURCE] callback returned from a useState (for a string variable), i.e.: <EmojiPicker selectionCallback={setMessage} />

import React, { useEffect, useRef, useState } from 'react'
import { createPopup, PopupPickerController } from '@picmo/popup-picker';
import styled from 'styled-components';
import smileySvg from '../../assets/icons/smiley.svg'

interface EmojiPickerProps {
  selectionCallback: React.Dispatch<React.SetStateAction<string>>;
}

const EmojiPicker: React.FC<EmojiPickerProps> = ({selectionCallback}) => {
  const smileyRef = useRef<HTMLImageElement | null>(null);
  const [picker, setPicker] = useState<PopupPickerController | null>(null);

  useEffect(() => {
    setPicker(createPopup({}, {
      triggerElement: smileyRef.current as HTMLElement,
      referenceElement: smileyRef.current as HTMLElement,
      position: 'bottom-start'
    }))
  }, []);

  useEffect(() => {
    if (!picker) return;
    picker.addEventListener('emoji:select', ({emoji})=> {
      selectionCallback((prevMessage) => prevMessage + emoji);
    });
  }, [picker, selectionCallback])

  const clickHandler = () => {
    if (!picker) return;
    picker.open()
  }

  return (
    <Smiley src={smileySvg} width="36" ref={smileyRef} onClick={clickHandler} />
  )
}

export default EmojiPicker;

const Smiley = styled.img``;
joeattardi commented 1 year ago

Still looking into this, but it looks like this error happens any time createPicker is called more than once. Hopefully will have a fix soon!

joeattardi commented 1 year ago

Since the DB population is asynchronous, I believe what's happening is that subsequent calls to createPicker happen before the initial DB is created, so it's in a weird state, and it tries to create it again.

joeattardi commented 1 year ago

Okay, I think I've got it.

I was able to reproduce your issue, and after the fix I made, I can no longer reproduce it. I think it's fixed! When you have a chance please try version 5.8.2 and let me know if the issue is resolved.

Feel free to reopen if you still run into issues.

afogel commented 1 year ago

Thank you!!!