Search code examples
javascriptreactjs

useDispatch - Maximum update depth exceeded


When I use the "useDisptach" with my Next.js app, I get the following error:

Maximum update depth exceeded.This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

store:

import { combineReducers, configureStore, createSlice } from "@reduxjs/toolkit";
import { createWrapper, MakeStore } from "next-redux-wrapper";

export type SystemData = {
  name: string;
};

export type SystemState = {
  data: SystemData | null;
};

const initialSystemState: SystemState = {
  data: { name: "Arif" },
};

export const systemSlice = createSlice({
  name: "system",
  initialState: initialSystemState,
  reducers: {
    systemLoaded(state, { payload }) {
      return (state = { ...state, data: { name: payload } });
    },
  },
});

export const { systemLoaded } = systemSlice.actions;

const reducers = {
  [systemSlice.name]: systemSlice.reducer,
};

const reducer = combineReducers(reducers);

const makeStore: MakeStore<any> = () => configureStore({ reducer });
type AppStore = ReturnType<typeof makeStore>;
export type AppState = ReturnType<AppStore["getState"]>;
export const wrapper = createWrapper<AppStore>(makeStore, { debug: true });

_app.tsx:

import { wrapper } from "@/store";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
import { Provider } from "react-redux";

export default function App({ Component, ...pageProps }: AppProps) {
  const { store } = wrapper.useWrappedStore(pageProps);
  return (
    <Provider store={store}>
      <Component {...pageProps} />;
    </Provider>
  );
}

my page:

"use client";
import { AppState, systemLoaded } from "@/store";
import { useDispatch, useSelector } from "react-redux";

const index = () => {
  const dispatch = useDispatch();
  const { data } = useSelector((state: AppState) => state.system);

  dispatch(systemLoaded("new name-1"));//if I disable this works fine
  return <div>Contact {data?.name}</div>;
};

export default index;

Solution

  • To fix this issue, you should use the useEffect hook to ensure that the dispatch action is only called once when the component mounts.

    Try this by adding dependency dispatch which will render only when dispatch is called.

     useEffect(() => {
            dispatch(systemLoaded("new name-1"));
          }, [dispatch]);
    

    Or you can just pass empty dependency. It will only run once when the component mounts.

     useEffect(() => {
            dispatch(systemLoaded("new name-1"));
          }, []);
    

    By adding dependency array it will either called when render or any dependency changes. It will stop calling infinite times.