DEV Community

Raj Ghodekar
Raj Ghodekar

Posted on • Edited on

Inside a emoji-picker-react: State, Events, and UI Patterns

lets understand what's going on under the hood of emoji-picker-react by @ealush a meta software developer.

Image description

link to emoji-picker-react
here's his website

(this is not how to use emoji-picker-react but what going on inside)

now straight to the repository, the library makes use of custom hooks and React.context very extensively and a BIG emphasis on that, its like one contextProvider after another and then another and then another, it keeps on going.

The App structure (not the folder structure)

Image description

It lifts all the necessary state, ref, and config inside contexts, and wraps the whole ui content, which makes it easier to access anything, at any leaf component.

This is known as the [Provider pattern]

(https://www.patterns.dev/vanilla/provider-pattern/), which prevents passing props down multiple layers, and use using them wherever required.

The Component accepts props with callbacks such as

onEmojiClick: (e)=>{},
onReactionClick:(e)=>{},
onSkinToneChange: (e)=>{},
previewConfig: {}
Enter fullscreen mode Exit fullscreen mode

these are for the user to pass callback handler functions to use the output and react to callbacks and also configs for the picker.

An intuitive way of open context api endpoints

, ( it's simple really, but for me, I haven't thought about passing them in this way)
Usually we create a Context, get all the values, build the state and create a simple :

const useMyContext = ()=> useContext(context)

The repository takes a different turn to exposing apis,

for Example

//usually we de-structure state right off the bat, but here its 
//just an object that is passed to the provider and then used when
//accessed. (global states everywhere which only means, one end 
//of your component can interact with another end without any 
//problems)

  const activeCategoryState = useState<ActiveCategoryState>(null);
  const emojisThatFailedToLoadState = useState<Set<string>>(new Set());
  const emojiVariationPickerState = useState<DataEmoji | null>(null);

  <PickerContext.Provider
      value={{
        activeCategoryState, 
        emojiVariationPickerState,
        emojisThatFailedToLoadState,
        ...
      }}
    >
      {children}
    </PickerContext.Provider>

//and then create a separate useContextHook for each, ( This is 
//more expressive, modular, and easier to follow — especially 
//when you're working with multiple context values -chatgpt. will
//update this once I get to the root why it's this way)

export function useEmojisThatFailedToLoadState() {
  const { emojisThatFailedToLoadState } = React.useContext(PickerContext);
  return emojisThatFailedToLoadState;
}

export function useIsPastInitialLoad(): boolean {
  const { isPastInitialLoad } = React.useContext(PickerContext);
  return isPastInitialLoad;
}

export function useEmojiVariationPickerState() {
  const { emojiVariationPickerState } = React.useContext(PickerContext);
  return emojiVariationPickerState;
}

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3muyjwtc9do0yyhpzo1.png)


//these are then later used to setVal or use val where  //required 
Enter fullscreen mode Exit fullscreen mode

Events

Events are absolutely critical to any UI component,
whether its keyboard events, auto closing modals or focusing inputs, better interactivity is what make a good user experience

Emoji picker stitches event listeners with custom hooks and the context state used from the context apis to the component as the component loads the eventListeners are active.

Image description
(not the most beautiful diagrammer am I)

For example

export function useOnFocus() {
  const BodyRef = useBodyRef();
  const emojiStyle = useEmojiStyleConfig();
  const getEmojiUrl = useGetEmojiUrlConfig();

  useEffect(() => {
    if (emojiStyle === EmojiStyle.NATIVE) {
      return;
    }

    const bodyRef = BodyRef.current;
    bodyRef?.addEventListener('focusin', onFocus);

    return () => {
      bodyRef?.removeEventListener('focusin', onFocus);
    };

    function onFocus(event: FocusEvent) {
    //do stuff
    }
  }, [BodyRef, emojiStyle, getEmojiUrl]);
}

function PickerRootElement({ children }: RootProps) {
  const [reactionsMode] = useReactionsModeState();
  const theme = useThemeConfig();
  ...
  useKeyboardNavigation();
  useOnFocus();

  return <div>...</div>

Enter fullscreen mode Exit fullscreen mode

Emoji-picker-react by @ealush is a great example of implementing contextApi in a way how it's meant to be used,
Applying separation of concerns and preventing hectic prop passing everywhere, and using react properly.

This has been a great learning, also in the future I will be doing more under the hood implementations of react libraries, as I get good at it ofcourse.

Top comments (0)