Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connect deeply nested independent components using React Context vs Event Bus

So I have a few deeply nested independent components that need to communicate with each other. For example I have a news overview which contains a feed, which can be collapsed/hidden from the navigation. The navigation is at a completely different place within the DOM than the news feed, hence passing props isn't really possible.

Since I have these kind of dependencies with multiple components, I have implemented a React Context for now to handle these states. To reach each and every component the context wraps the whole app.

Is this a good practice or should I go for a kind of EventBus instead?

const eventBus = {
  on(event, callback) {
    // ...
  },
  dispatch(event, data) {
    // ...
  },
  remove(event, callback) {
    // ...
  },
};

vs

<CustomThemeProvider>
     <Component {...pageProps} /> // app
</CustomThemeProvider>

What's the best practice here?

like image 283
Tim Avatar asked Oct 29 '25 10:10

Tim


1 Answers

Consider this code fragment:

      //providers
      <AccountContext.Provider value={{...this.state, onAccountLastVisited}}>
          ...
          <VersionContext.Provider value={{...this.state, onUpdateVersion}}>
              ...
              <TrackingContext.Provider value={{...this.state, onCodeTracking}}>
                  ...
                  <NotificationContext.Provider value={{...this.state, onSendNotification}}>
      //consumers
      <AccountContext.Consumer>{accContext=> {
          ...
          <VersionContext.Consumer>{verContext=> {
              ...
              <TrackingContext.Consumer>{trkContext=> {
                  ...
                  <NotificationContext.Consumer>{nftContext=> {
                      const {onAccountLastVisited} = accContext;
                      const {onUpdateVersion     } = verContext;
                      const {onCodeTracking      } = trkContext;
                      const {onSendNotification  } = nftContext;
                      ...
                      ... onSubmit={()=> {
                              onAccountLastVisited(eventData);
                              onUpdateVersion     (eventData);
                              onCodeTracking      (eventData);
                              onSendNotification  (eventData);
                          };}
  1. That looks ugly asf.

  2. Tightly coupled with the knowledge of components outside everywhere.

  3. Component is polluted and you have to come back to edit this thing whenever you come up with a new context provider/consumer.

Don't know about you, but it hurts my eyes.

Now on the other hand:

    //listener
    EventBus.on('TaskForm.submitClick', onAccountLastVisited);
    ...
    //caller
    ... onSubmit={()=> {
        EventBus.dispatch('TaskForm.submitClick', eventData);
    }

That's it.

  1. Now this component knows nothing about its parents or providers, completely decoupled.

  2. Very clean. Any context module can listen to the event and do the context update.

  3. Doesn't matter if your component event is travelling up, down, or side ways.

I DO NOT see why we don't use the event bus. Full disclosure here, I am not a React expert. If anyone can give me a better reason why I should stick with the providers, I am all ears.


[EDIT]

Re-visiting my answer. It turns out there are eventBus-style packages out there you can use.

Akita is built for RxJS package like observable-hooks.js. Good for running loose coupling structure.

Or Recoil that is also loose coupling design with Atom getter & setters that you can do things in them.

Or React Query. This is not an eventBus style package. However, it gives you not just context management, but also everything to be looked after including advanced cache management. Highly recommanded.

The last one is the good old Redux RTK RTKQ, which I peronally find over-engineered, and tbh I would pick React Query over RTK/Q whenever I could.

Please take a look at 'Picking From 20 React State Managers' from Jack Herrington posted on Jan 4, 2022. So, just about a month after you asked the question. He has summerised everything quite well.

like image 51
Tom Avatar answered Nov 01 '25 00:11

Tom



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!