Replace redux with context and reducer hook in react


Posted 4 months ago by Ryan Dhungel

Category: React Hooks

Viewed 605 times

Estimated read time: 2 minutes

  • We can create redux like architecture to create a global state using useReducer and useContext hook
  • With the introduction of useReducer and useContext hooks
  • We can create a global state to manage data, application wide without using redux
  • When you have a global state, all your components can easily access/supply data to the global state
  • which makes updating and flowing data to components really easily

 

Example of creating redux like global state using useContext and useReducer hook

 

import React, { useState, useReducer, useContext, createContext } from "react";

// initial state
const initialState = { user: null };

// create context
const StateContext = createContext({
  user: null,
  dispatch: f => f
});

// auth reducer
// using ... spread operator to spread state values
// and return new state based on action payload
const authReducer = (state, action) => {
  switch (action.type) {
    case "LOGIN":
      return {
        ...state,
        user: action.payload
      };
    case "LOGOUT":
      return {
        ...state,
        user: null
      };
    default:
      return state;
  }
};

// context provider / App component
const App = () => {
  const [state, dispatch] = useReducer(authReducer, initialState);

  return (
    <StateContext.Provider value={{ state, dispatch }}>
      <Login />
    </StateContext.Provider>
  );
};

// context consumer component
const Login = () => {
  // destructure state and dispatch from context
  const { state, dispatch } = useContext(StateContext);
  const [name, setName] = useState("");

  const handleSubmit = e => {
    e.preventDefault();
    dispatch({ type: "LOGIN", payload: name });
  };

  const handleLogout = () => {
    dispatch({ type: "LOGOUT" });
    setName("");
  };

  return (
    <div>
      Current user: {state.user ? state.user : "null"}
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          value={name}
          onChange={e => setName(e.target.value)}
        />
      </form>
      <br />
      {state.user && <button onClick={handleLogout}>Logout</button>}
    </div>
  );
};

export default App;