Master Global State Management in React with Custom Hooks
Learn how to build a simple global state management solution in React using custom hooks, starting from a basic counter component, extending it with initialization props, synchronizing multiple counters, and finally creating a reusable createGlobalState utility for shared state across components.
Example of developing a counter component, introducing a method to implement global state management using React Hooks.
Simple Counter Component
Below is a simple counter component named Counter that starts counting from 0 and increments by one on each click:
const Counter = ({ text }) => {
const [count, setCount] = useState(0);
const addCount = () => setCount(count + 1);
return (
<div onClick={addCount}>
{text}: {count}
</div>
);
};We can further abstract the above Counter using a custom hook useCounter to implement the counting logic:
const useCounter = (initCount) => {
const [count, setCount] = useState(initCount || 0);
const addCount = () => setCount(count + 1);
return [count, addCount];
};
const Counter = ({ text }) => {
// Use custom hook useCounter
const [count, addCount] = useCounter(0);
return (
<div onClick={addCount}>
{text}: {count}
</div>
);
};Both implementations produce the same functionality. We can render two counters using the Counter component:
const APP = () => {
return (
<div>
<Counter text="计数器1" />
<Counter text="计数器2" />
</div>
);
};Result:
Counter with Initial Value
The two counters are independent. By adding an initCount prop to Counter, we can set the initial value:
const useCounter = (initCount) => {
const [count, setCount] = useState(initCount || 0);
// Component updates its own count
const addCount = () => setCount(count + 1);
// Reset count when initCount changes
useEffect(() => {
setCount(initCount);
}, [initCount]);
return [count, addCount];
};
const Counter = ({ initCount, text }) => {
const [count, addCount] = useCounter(initCount);
return (
<div onClick={addCount}>
{text}: {count}
</div>
);
};
const APP = () => {
return (
<div>
<Counter initCount={1} text="计数器1" />
<Counter initCount={0} text="计数器2" />
</div>
);
};Synchronized Counters
To make two counters update synchronously, share the count state in the parent component and pass both the count and a change handler to each counter via an onChange prop:
const useCounter = (initCount, onChange) => {
const [count, setCount] = useState(initCount || 0);
const addCount = onChange || (() => setCount(count + 1));
useEffect(() => {
setCount(initCount);
}, [initCount]);
return [count, addCount];
};
const Counter = ({ initCount, onChange, text }) => {
const [count, addCount] = useCounter(initCount, onChange);
return (
<div onClick={addCount}>
{text}: {count}
</div>
);
};
const APP = () => {
const [count, setCount] = useState(0);
const addCount = () => setCount(count + 1);
return (
<div className="App">
<Counter initCount={count} text="计数器1" onChange={addCount} />
<Counter initCount={count} text="计数器2" onChange={addCount} />
</div>
);
};Result:
We can further simplify by using a single custom hook for global state:
const APP = () => {
const [count, addCount] = useCounter(0);
return (
<div className="App">
<Counter initCount={count} text="计数器1" onChange={addCount} />
<Counter initCount={count} text="计数器2" onChange={addCount} />
</div>
);
};More General Global State Management
Upgrade the code to a reusable createGlobalState utility for simple global state management:
const createGlobalState = (initialState) => {
let globalState = initialState;
const listeners = new Set();
const setGlobalState = (nextGlobalState) => {
globalState = nextGlobalState;
listeners.forEach((listener) => listener());
};
const useGlobalState = () => {
const [state, setState] = useState(globalState);
useEffect(() => {
const listener = () => setState(globalState);
listeners.add(listener);
listener();
return () => listeners.delete(listener);
}, []);
return [state, setGlobalState];
};
return {
setGlobalState,
useGlobalState,
};
};Using createGlobalState for state management:
const { useGlobalState } = createGlobalState(0);
const Counter = ({ text }) => {
const [state, setGlobalState] = useGlobalState();
return (
<div onClick={() => setGlobalState(state + 1)}>
{text}: {state}
</div>
);
};
const App = () => {
const [state] = useGlobalState();
return (
<div className="App">
<Counter text="计数器" />
<div>点击次数:{state}</div>
</div>
);
};Result:
This simple implementation is limited; for a more complete solution, see the react-hooks-global-state library, which inspired this article.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
