Sharing state between unrelated React components

Want to show how you can share any serializable data between React components, e.g. client components in NextJS.

We have few unrelated components:

Let’s create a object that will contain initial state

export const state: { count: number } = { co…


This content originally appeared on DEV Community and was authored by Alex

Want to show how you can share any serializable data between React components, e.g. client components in NextJS.

We have few unrelated components:

Example app UI

Let's create a object that will contain initial state

export const state: { count: number } = { count: 0 };

We can store data in a Map or a WeakMap, state will be a key to access it. Also, will need a subscribers array.

const stateMap = new WeakMap<object, object>();
const subscribers: (() => void)[] = [];

Now let's write a hook to subscribe to data changes.

export function useCommonState<T extends object>(stateObj: T) {
  // more efficient than `useEffect` since we don't have any deps
  React.useInsertionEffect(() => {
    const cb = () => {
      const val = stateMap.get(stateObj);
      _setState(val!);
    };
    // subscribe to events
    subscribers.push(cb);

    return () => {
      subscribers.slice(subscribers.indexOf(cb), 1);
    };
  }, []);
}

Now let's add logic related to get and set state

  // all instances of hook will point to same object reference
  const [state, _setState] = React.useState<typeof stateObj>(() => {
    const val = stateMap.get(stateObj) as T;
    if (!val) {
      stateMap.set(stateObj, stateObj)
      return stateObj
    }
    return val
  });

  const setState = React.useCallback((newVal: object) => {
    // update value
    stateMap.set(stateObj, newVal);
    // notify all other hook instances
    subscribers.forEach((sub) => sub());
  }, []);

  return { state, setState };

And now can use it in 3 components like

import { state as myState } from './state';
//...

const { state, setState } = useCommonState(myState);

<button
  onClick={() => setState({ count: state.count + 1 })}
  className="p-2 border"
>
  +
</button>
// ...
Component A<div>Count: {state.count}</div>

Final app

You can see how it works here https://stackblitz.com/~/github.com/asmyshlyaev177/react-common-state-example?file=app/page.tsx
Or in github https://github.com/asmyshlyaev177/react-common-state-example

Check out my library for NextJS based on this principle https://github.com/asmyshlyaev177/state-in-url

Tnx for reading.


This content originally appeared on DEV Community and was authored by Alex


Print Share Comment Cite Upload Translate Updates
APA

Alex | Sciencx (2024-07-11T14:32:37+00:00) Sharing state between unrelated React components. Retrieved from https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/

MLA
" » Sharing state between unrelated React components." Alex | Sciencx - Thursday July 11, 2024, https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/
HARVARD
Alex | Sciencx Thursday July 11, 2024 » Sharing state between unrelated React components., viewed ,<https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/>
VANCOUVER
Alex | Sciencx - » Sharing state between unrelated React components. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/
CHICAGO
" » Sharing state between unrelated React components." Alex | Sciencx - Accessed . https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/
IEEE
" » Sharing state between unrelated React components." Alex | Sciencx [Online]. Available: https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/. [Accessed: ]
rf:citation
» Sharing state between unrelated React components | Alex | Sciencx | https://www.scien.cx/2024/07/11/sharing-state-between-unrelated-react-components/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.