seniv / react-native-notifier

Fast and simple in-app notifications for React Native
MIT License
1.05k stars 60 forks source link

Temporary NotifierRoot to enable notifications in react-modal #61

Closed kristofferso closed 2 years ago

kristofferso commented 2 years ago

Hey! Really enjoying this clean library! I'm trying to get it to work with react modals, but as I saw in another issue, notifications are rendered behind modals because they are native components. I have been able to work around it by adding a NotifierRoot component inside my modal. Nofications triggered from inside the modal are visible there. Great! However, when the modal is closed future notifications are referencing an unmounted component.

Is there any way of reverting or unmounting the NotifierRoot?

Thanks! 🙏

kristofferso commented 2 years ago

I was able to solve this by using a custom context hook with the NotifierWrapper and NotifierRoot with a ref applied to it. All notifications in the main window (not modal) needs to be explicitly called on the ref of the NotifierRoot in the hook. In all modals where you want to display a notification you need to include a <NotifierRoot /> somewhere inside the modal. I ended up putting that in a modal wrapper component that I was already using for all my modals.

Heres my custom hook:

import React, {createContext, useContext, useRef} from 'react';
import {Notifier, NotifierRoot, NotifierWrapper} from 'react-native-notifier';

const Context = createContext();

const Provider = ({children}) => {
  const notificationRef = useRef();

  const showNotification = (notificationObject) => {
    notificationRef.current?.showNotification(notificationObject);
  };

  const showModalNotification = (notificationObject) => {
    Notifier.showNotification(notificationObject);
  };

  const exposed = {
    showNotification,
    showModalNotification,
  };

  return (
    <Context.Provider value={exposed}>
      <NotifierWrapper>
        <NotifierRoot ref={notificationRef} />
        {children}
      </NotifierWrapper>
    </Context.Provider>
  );
};

export const useNotifications = () => useContext(Context);

export default Provider;

Usage in a component:

const {showNotification} = useNotifications()

...
return (
<>
<Button onPress={()=>{showNotification({title="Success!"})} />
</>
)

Usage inside a modal:

const {showModalNotification} = useNotifications()

...
return (
<>
<NotifierRoot />
<Button onPress={()=>{showModalNotification({title="Success!"})} />
</>
)