This repository is proof of concept of implementing PubSub architecture in react using react context, swr and wretch.
Sometimes it's needed to revalidate data fetched and displayed by components that were mounted and possibly will be mounted again in the future. For example, user goes to list of some resources, then goes to page where can create new resource, then gets back to list of resources.
What happened here is:
- List of resources (mount some component List, mount hooks likeuseGetApi, fetch data by those hooks)
- Go to create page (mount new component Create, mount hooks likeuseUpdateApi, unmountListanduseGetApi)
- Create resource (use useUpateApi)
- Go back to list of resources (mount ListanduseGetApiagain)
The problem is in step 3. where there is no way to notify List component that data has changed and it should be
revalidated.
In case of using eventEmitter and eventListner it would be:
- Create resource (use useUpateApi), and emit eventresourceCreated
- Go back to list of resources (mount ListanduseGetApiagain), and listen to eventresourceCreated
But in fact List and useGetApi were not mounted when event was emitted, so it didn't get notified.
To achieve expected behaviour, we need to store events somewhere and then notify components during their mount phase.
This project shows how to use PubSub pattern and simplified actor's model mailboxes to store events and notify unmounted (that will probably mount again in the future) about need of data revalidation.
Publisher - some hook or component that can notify others about need of data revalidation Subscriber - some hook or component that can be notified about need of data revalidation
- Publisher can emit event only when it's mounted
- Publisher can emit only one event at a time
- Single event can be delivered to multiple subscribers
- Subscribers are ephemeral, they can be mounted and unmounted multiple times
- Subscribers doesn't store it's state
- When subscriber mounts, it should be notified about all events that were emitted when it was unmounted
- When subscriber is mounted, it should react in real time to events emitted by publishers
- When subscriber is unmounted, it should stop reacting to events emitted by publishers
- Application is wrapped by PubSubProviderwhich contains logic of subscription, unsubscription and notification processes
// _app.tsx
const App = ({Component, pageProps}: AppProps) => (
  <PubSubProvider>
    <SWRConfig>
      <Component {...pageProps} />
    </SWRConfig>
  </PubSubProvider>
);- Hooks responsible for fetching data subscribes and unsubscribes to events
export const useGetApiData = (url: string) => {
  // ... some code to fetch data
  // some method to revalidate data
  const mutate = () => {
  }
  const {subscribe, unSubscribe} = usePubSub();
  useEffect(() => {
    const events: IEvent[] = ["USER_CREATED", "USER_DELETED"];
    subscribe({
      events: events,
      url: url,
      callback: () => {
        mutate();
      },
    });
    return () => {
      unSubscribe({
        events: events,
        url: url,
        callback: () => {
          mutate();
        },
      });
    };
  }, [mutate, subscribe, unSubscribe, url]);
  return {data, isLoading, error};
};- Hooks or component responsible for data updated emits event
export const RefreshButtons = () => {
  const {dispatch} = usePubSub();
  return (
    <div>
      <button
        onClick={() => {
          dispatch("USER_CREATED");
        }}
      >
        emit event
      </button>
    </div>
  );
};Take a look at comments in PubSubProvider.tsx
pnpm install
pnpm run devTo see exact behaviour, open network tab in dev tools and see observe requests to /api/dummy