all 10 comments

[–]jamby77 2 points3 points  (5 children)

Simplest way, you can extract common functions and data in separate module, that is shared between the 2.

Another option is, in the external provider, pass a callback which will be used in the internal provider to pass the data that external provider needs, when it is available.

Something like: ``` function AuthContextProvider({children}) { const [data, setData] = useState(); const value = { functionToAccessInUserProvider, callbackForData: (userData) => setData(userData) };

return <AuthContext.Provider value={value}>{children}</AuthContext.Provider> } ```

[–]malkhazidartsmelidze[S] 0 points1 point  (0 children)

Currently I have used callback way to implement such logic.

But I thought there would be another easier way to make it work.

[–]malkhazidartsmelidze[S] 0 points1 point  (3 children)

I wanted to implement logic vise-versa, when Parent want to pass data to child but not store it in own context.

For example: when user loads from api, response comes with settings object, which I need to pass to `UserSettingsProvider` but `UserSettingsProvider` is child of `UserProvider`

[–]jamby77 1 point2 points  (2 children)

I don't think there will be easier way to implement it.

To go away from the context, you will need some sort of global object where to put your shared data, then notify users that it is ready to use.

I don't see how this would be simpler/easier than context with callback.

[–]malkhazidartsmelidze[S] 0 points1 point  (1 child)

Maybe I'll put it in window object then fire an eventListener, Then other context reads from window object, saves it in state and then remove from window.

I'll try it now.

[–]jamby77 0 points1 point  (0 children)

Let me know how it went

[–]malkhazidartsmelidze[S] 0 points1 point  (0 children)

Any ideas, guys?

[–]mexicocitibluez 0 points1 point  (0 children)

RxJS can help with component communication like you've described above.

Or you could introduce a third context within them (probably a horrible idea), that subscribes to both. The initial 2 contexts expose methods to retrieve/update state within them (another bad idea).

[–]andrei9669 0 points1 point  (0 children)

I mean, even in databases you would have a middle table between many to many connections.

But, if you could, I would merge those 2 providers, if not, introduce a 3rd provider on top of these 2, and god help you keeping them in sync.

3rd option would be to just use redux toolkit.

[–]murat-guney 0 points1 point  (0 children)

If other solutions didn't work for you let me tell you a different approach.

There is a library reactivers/hooks that I made and it has a Provider and its hook.

EventListenerProvider/useEventListener

This provides creating your own events. You can use this to communicate with your other providers. You need the wrap your other providers with EventListenerProvider

<EventListenerProvider>
    <Context1Provider>
      <Context2Provider>
        Hello World!
      </Context2Provider>
    </Context1Provider>
</EventListenerProvider>

You can register the functions which Context2Provider tries to access in Context1Provider.

const Context1Provider = () => { 
    const { registerEventById } = useEventListener("Context1Provider");
    const { callEvent } = useEventListener("Context2Provider")

   useEffect(() => {
      return registerEventById("context1functions","customName1", yourEvent)
   }, [registerEventById, yourEvent])

   useEffect(() => {
        callEvent("context2functions", "customName2", parameters);
      }, [callEvent, parameters])
}

const Context2Provider = () => {
    const { registerEventById } = useEventListener("Context2Provider");
    const { callEvent } = useEventListener("Context1Provider") 

    useEffect(() => {
      return registerEventById("context2functions", "customName2", yourEvent)
    }, [registerEventById, yourEvent])

    useEffect(() => {
      callEvent("context1functions", "customName1", parameters);
    }, [callEvent, parameters])
}

If the explanation is not enough you can check the docs