You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello, thanks for this good library. I've always used it well.
I'm opening this issue because I have a suggestion.
I found that the dispatch is declared as global variable. In a situation that you have a single provider, this isn't a big deal. But this is problem if you are using more than one provider.
When NiceModal.provider is called, the global dispatch is updated with givenDispatch or new dispatch function that returned from useReducer hook.
constInnerContextProvider: React.FC=({ children })=>{constarr=useReducer(reducer,initialState);constmodals=arr[0];dispatch=arr[1];// update with new dispatchreturn(<NiceModalContext.Providervalue={modals}>{children}<NiceModalPlaceholder/></NiceModalContext.Provider>);};exportconstProvider: React.FC<Record<string,unknown>>=({
children,dispatch: givenDispatch,modals: givenModals,}: {children: ReactNode;dispatch?: React.Dispatch<NiceModalAction>;modals?: NiceModalStore;})=>{if(!givenDispatch||!givenModals){return<InnerContextProvider>{children}</InnerContextProvider>;}dispatch=givenDispatch;// update with givenDispatchreturn(<NiceModalContext.Providervalue={givenModals}>{children}<NiceModalPlaceholder/></NiceModalContext.Provider>);};
If you use multiple providers, the global dispatch will be updated with dispatch function intended by the last called provider. And every modals will only be rendered under this last provider because all methods in library (like NiceModal.show) use global dispatch.
functionSomeApp(){return(<NiceModal.Provider>// update global dispatch<SomeArea/><NiceModal.Provider>// update global dispatch again// the modal dispatched in 'SomeArea' will be rendered here </NiceModal.Provider/><NiceModal.Provider/>)}
I know that this is not common case.
In our team, we open new window and render components with react portal. In this case we should use multiple providers to render modals in new window.
functionNewWindow({ children }){const[container]=useState(()=>{constnewWindow=window.open()constcontainer=newWindow.document.createElement('div')newWindow.document.body.append(container)returncontainer})returnReactDOM.createPortal(children,container)}functionSomeApp(){return(<NiceModal.Provider>
...
<NewWindow><NiceModal.Provider>
...
</NiceModal.Provider></NewWindow></NiceModal.Provider>)}
So I suggest following.
provide dispatch function with context
constInnerContextProvider: React.FC=({ children })=>{constarr=useReducer(reducer,initialState);constmodals=arr[0];dispatch=arr[1];return(<NiceModalContext.Providervalue={modals}><NiceModalDispatchContext.Providervalue={dispatch}{children}</NiceModalDispatchContext.Provider><NiceModalPlaceholder/></NiceModalContext.Provider>);};
use the dispatch from context in showCallback that is returned by useModal hook
Nested usage is only a subset of the problem - the same problem occurs with providers in different places in the React tree.
We have this issue in a shadow DOM context. That would usually be a web component, but we're using it for micro-frontends, where parts of the ui are in isolated containers with their own shadow DOMs. I was quite surprised to see modals rendered inside another shadow DOM - I was expecting the NiceModal.Provider context to contain everything, also registered modals etc, so that each provider would work independently from each other, just by using the closest provider ancestor.
Hello, thanks for this good library. I've always used it well.
I'm opening this issue because I have a suggestion.
I found that the
dispatch
is declared as global variable. In a situation that you have a single provider, this isn't a big deal. But this is problem if you are using more than one provider.When NiceModal.provider is called, the global dispatch is updated with
givenDispatch
or new dispatch function that returned from useReducer hook.If you use multiple providers, the global dispatch will be updated with dispatch function intended by the last called provider. And every modals will only be rendered under this last provider because all methods in library (like NiceModal.show) use global dispatch.
I know that this is not common case.
In our team, we open new window and render components with react portal. In this case we should use multiple providers to render modals in new window.
So I suggest following.
Thanks for reading.
Please consider and respond.
The text was updated successfully, but these errors were encountered: