Combining useContext
with useReducer
in React allows you to manage a global state more effectively by providing a centralized state management solution.
How to combine useContext with useReducer?
-
Create a Context: First, you need to create a context to hold your global state and provide it to your component tree. You can use the
React.createContext()
function for this purpose. - Define a Reducer: Define a reducer function that specifies how state transitions should occur in response to dispatched actions. The reducer takes the current state and an action as arguments and returns the new state.
-
Use
useReducer
Hook: Inside your component, use theuseReducer
hook to manage state transitions based on dispatched actions. This hook returns the current state and a dispatch function, which is used to send actions to the reducer. -
Use
useContext
Hook: Use theuseContext
hook to access the state and dispatch function provided by the context.
Example: Below is an example of combining useContext with useReducer.
-
We create a context called
GlobalStateContext
. - We define a reducer function that manages state transitions for a simple counter.
-
We use the
useReducer
hook inside theGlobalStateProvider
component to manage the global state. -
We provide the state and dispatch function to the context using
GlobalStateContext.Provider
. -
We use
useContext
to access the state and dispatch function in theCounter
component. -
Finally, we wrap our
Counter
component with theGlobalStateProvider
in theApp
component to make the global state available to it.
Javascript
import React, { createContext,
useContext,
useReducer
} from 'react' ;
// Step 1: Define a context const CounterContext = createContext(); // Step 2: Define a reducer function const reducer = (state, action) => { switch (action.type) {
case 'increment' :
return { count: state.count + 1 };
case 'decrement' :
return { count: state.count - 1 };
default :
return state;
}
}; /* Step 3: Create a component that provides the context and manages state with useReducer
*/
function CounterProvider({ children }) {
const [state, dispatch] = useReducer(reducer,
{ count: 0 });
// Log the state whenever it changes
console.log( 'Counter state:' , state);
return (
<CounterContext.Provider value={{
state,
dispatch
}}>
{children}
</CounterContext.Provider>
);
} // Step 4: Create a custom // hook to access the context function useCounter() {
const context = useContext(CounterContext);
if (!context) {
throw new Error(`useCounter must be used
within a CounterProvider`);
}
return context;
} /* Step 5: Use the custom hook to access
state and dispatch actions
*/
function Counter() {
const { state, dispatch } = useCounter();
return (
<div>
<h2>Counter: {state.count}</h2>
<button onClick={
() => dispatch({
type: 'increment'
})
}>
Increment
</button>
<button onClick={
() => dispatch({
type: 'decrement'
})
}>
Decrement
</button>
</div>
);
} function App() {
return (
<CounterProvider>
<Counter />
</CounterProvider>
);
} export default App;
|
Output: