1

Below is my code, whatever action i dispatch using the below reducer, dispatch is called twice. I have read that reducers must be pure functions and no side effects or api calls to be made from a reducer. Else this behaviour is expected. What am i missing? Is my function impure?

const modalInitialState = {
    Id: "",
    Name: "",
    PhoneNumber: "",
    Email: "",
    IsOpen: false,
    Header: null,
    Mode: null,
  };

  const modalActions = {
    ADD: "ADD",
    UPDATE: "UPDATE",

    CANCEL: "CANCEL",
    ON_CHANGE: "ON_CHANGE",

    OPEN_AS_ADD: "OPEN_AS_ADD",
    OPEN_AS_UPDATE: "OPEN_AS_UPDATE",
  };

  const modalReducer = (state, action) => {
    switch (action.type) {
      
      case modalActions.CANCEL:
        return modalInitialState;
        break;
      case modalActions.ON_CHANGE:
        switch (action.id.toLowerCase()) {
          case "name":
            return { ...state, Name: action.val };
            break;
          case "phonenumber":
            return { ...state, PhoneNumber: action.val };
            break;
          case "email":
            return { ...state, Email: action.val };
            break;
        }
        break;
      case modalActions.OPEN_AS_ADD:
        return { ...state, IsOpen: true, Header: "Add", Mode: "Add" };
        break;
      case modalActions.OPEN_AS_UPDATE:
        return { ...state, IsOpen: true, Header: "Update", Mode: "Update" };
        break;
      case modalActions.CANCEL:
        return { ...state, IsOpen: false };
        break;
      case modalActions.ADD:
        return modalInitialState;
        break;
    case modalActions.UPDATE:
        return modalInitialState;
        break;
      default:
        return state;
        
    }
  };
  const [modalState, modalDispatch] = useReducer(
    modalReducer,
    modalInitialState
  );
  const OnChangeHandler = (event) => {
modalDispatch({
  type: modalActions.ON_CHANGE,
  id: event.target.id,
  val: event.target.value,
});

};

  • Are your components wrapped in strict mode? If yes, checkout this answer https://stackoverflow.com/a/72112129/11719314 – Som Shekhar Mukherjee May 08 '22 at 18:33
  • Does this answer your question? [useReducer dispatch being called twice](https://stackoverflow.com/questions/72068781/usereducer-dispatch-being-called-twice) – nCessity Jul 04 '23 at 13:32

1 Answers1

2

You're probably experiencing this because your application is running in StrictMode. And in StrictMode, during development, reducers are called twice to help developers catch certain bugs in their app. So, you aren't dispatching the action twice but React is calling the reducer twice on its own because you're in StrictMode.

I've a detailed answer about how strict mode works and behaves, you can check it out here.

The example below shows how during development (snippet uses the development build of React) when in StrictMode, reducers run twice.

const countReducer = (count, incrementor) => {
  console.log("Reducer ran");
  return count + incrementor;
};

function App() {
  const [count, incrementCount] = React.useReducer(countReducer, 0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => incrementCount(1)}>Increment</button>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div id="root"></div>
Som Shekhar Mukherjee
  • 4,701
  • 1
  • 12
  • 28