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.
没有评论:
发表评论