Not sure if this is a so-called "pub/sub" pattern or a form of a "pub/sub" pattern. I am trying to create a piece of shared state so that different components can subscribe to it and only gets updated when there is an update with that state.
const useForceUpdate = () => useReducer((state) => !state, false)[1];
const createSharedState = (reducer, initialState) => {
const subscribers = [];
let state = initialState;
const dispatch = (action) => {
state = reducer(state, action);
subscribers.forEach((callback) => callback());
};
const useSharedState = () => {
const forceUpdate = useForceUpdate();
useEffect(() => {
const callback = () => forceUpdate();
subscribers.push(callback);
const cleanup = () => {
const index = subscribers.indexOf(callback);
subscribers.splice(index, 1);
};
return cleanup;
}, []);
return [state, dispatch];
};
return useSharedState;
};
const initialState = 0;
const reducer = (state, action) => {
switch (action.type) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
case "set":
return action.count;
default:
return state;
}
};
const useCount1 = createSharedState(reducer, initialState);
const useCount2 = createSharedState(reducer, initialState);
const Counter = ({ count, dispatch }) => (
<div>
{count}
<button onClick={() => dispatch({ type: "increment" })}>+1</button>
<button onClick={() => dispatch({ type: "decrement" })}>-1</button>
<button onClick={() => dispatch({ type: "set", count: 0 })}>reset</button>
</div>
);
const Counter1 = () => {
const [count, dispatch] = useCount1();
return <Counter count={count} dispatch={dispatch} />;
};
const Counter2 = () => {
const [count, dispatch] = useCount2();
return <Counter count={count} dispatch={dispatch} />;
};
const Example = () => (
<>
<Counter1 />
<Counter1 />
<Counter2 />
<Counter2 />
</>
);
Here is a live demo: https://codesandbox.io/s/pubsub-q716s?file=/src/App.js
It seems to be working fine. My questions are:
- Is this a valid way to implement shared update subscription?
- Is there any drawbacks with using a simple variable to hold the state + forcing React to re-render if that piece of state changes, instead of using
useState
oruseReducer
as one normally would do? - any feedback is welcomed.
from React: is this a good way to implement a shared state subscription?
No comments:
Post a Comment