-1

useReducer function is giving different answers with and without strict mode enabled. With strict mode enabled my count is increasing by 2 with every click and without strict mode, count increasing by 1.I understand that in strict mode the reducer function is called twice but updating the state inside the function increasing the count by 2 while the same thing, if i do with setState then the count always increases by 1. In both usestate and usereducer function, the function renders two times but why the output differs.

import { useState, useReducer } from "react";
import styles from "./App.module.css";

const reducer = (state, action) => {
  if (action.type === "INCREMENT") {
    state.count = state.count + 1;
    console.log(state);
    return { count: state.count };
  }
  return state;
};
function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });
  const increment = () => {
    dispatch({ type: "INCREMENT" });
  };
  return (
    <div>
      <button onClick={increment}>+</button>
      {state.count}
      <button>-</button>
    </div>
  );
}

export default App;

I want to know how exactly use reducer works behind the scenes with strict mode enabled and disabled. Why the output differs if i increment the state and return the state vs incrementing the state while returning.

1 Answers1

0

I am not sure if I'm right but i think the issue is because we have the non-primitive type (object) and the object is referred based on memory so the update to any key of object persists in the memory and that's why the increment is done by 2. So, due to react strict mode the reducer function runs twice and the increment done during the first time reducer function invocation persists during the second time render and eventually during committing, we see an increment of 2. Also i tried the same thing with a primitive datatype (integer in my case), the increment happened by 1 only even though i updated the state directly and not during returning.

import { useState, useReducer } from "react";
import styles from "./App.module.css";

const reducer = (state, action) => {
  if (action.type === "INCREMENT") {
    state += 1;
    console.log(state);
    return state;
  }
  return state;
};
function App() {
  const [state, dispatch] = useReducer(reducer, 0);
  const increment = () => {
    dispatch({ type: "INCREMENT" });
  };
  return (
    <div>
      <button onClick={increment}>+</button>
      {state}
      <button>-</button>
    </div>
  );
}

export default App;

Please correct me if I am wrong.