Open In App

How to combine useContext with useReducer?

Last Updated : 21 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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 the useReducer 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 the useContext 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 the GlobalStateProvider 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 the Counter component.
  • Finally, we wrap our Counter component with the GlobalStateProvider in the App 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:

gfg41

Output



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads