Take Latest Redux Saga Infinite Loop

29 views Asked by At

We have a Redux Saga that seems to loop infinitely for some reason and we are unsure why/how that is happening. For the record, this code was previously working as is but we just recently upgraded our frontend codebase, node and project libraries to newer versions, so perhaps there was a change in how this functionality in Redux Saga works.

React component:

// AG-Grid library callback
getDetailRowData: (params) => {
      const { id } = params.data;
      // This is where the loop occurs in the render

      dispatch(
        reduxSagaFunction({
          accessToken,
          id,
          onSuccess: (data) => {
            const rows = getDetailTableRows(data);

            params.successCallback(rows);
          },
          onFail: () => {
            params.successCallback([]);
          },
        })
      );
    },

Slice:

reduxSagaFunction: (state, action) => {
      const { id } = action.payload;

      state.reduxSagaFunctionLoading[id] = true;
      state.reduxSagaFunctionLoaded = null;
    },
    reduxSagaFunctionSuccess: (state, action) => {
      const { id, data } = action.payload;

      state.reduxSagaFunctionLoading[id] = false;
      state.reduxSagaFunctionLoaded[id] = data;
      state.reduxSagaFunctionError[id] = null;
      state.reduxSagaFunctionLoadedRequest = { id, data };
    },
    reduxSagaFunctionError: (state, action) => {
      const { id, message } = action.payload;

      state.reduxSagaFunctionLoading[id] = false;
      state.reduxSagaFunctionError[id] = message;
    },

Saga:

export function* reduxSagaFunctionSaga({ payload }) {
  const { accessToken, id, onFail, onSuccess } = payload;

  try {
    const response = yield call(
      fetch,
      `url`,
      {
        headers: {
          Authorization: `Bearer ${accessToken}`,
        },
      }
    );

    if (response.status !== 200) {
      throw new Error("Failed to load");
    }

    const data = yield response.json();

    ==================> // This is the function that seems to loop the saga infinitely.  
    // If I comment this out, then the loop does not occur.**
    yield put(reduxSagaFunctionSuccess({ id, data }));

    if (onSuccess) {
      yield call(onSuccess, data);
    }
  } catch ({ message }) {
    yield showError(message);
    yield put(reduxSagaFunctionError({ id, message }));
    if (onFail) {
      yield call(onFail);
    }
  }
}

export default function* reduxSaga() {
  yield all([
    takeLatest(
      reduxSagaFunction.type,
      reduxSagaFunctionSaga
  ]);

Relevant versions:

node: 20.10.0
react: 16.14.0
react-redux: 8.1.3
redux-saga: 1.3.0

I am under the impression that somehow takeLatest might be the culprit, but I have been unable to figure out what might have changed between versions that would change the behavior.

Edit:
I think I have found what might be occurring, and it is in the redux middleware configuration. This was originally created with the original version of our application.

function getStore(preloadedState) {
  const sagaMiddleware = createSagaMiddleware();
  const store = configureStore({
    preloadedState: preloadedState,
    middleware: [
      ...getDefaultMiddleware({
        thunk: false,
        serializableCheck: {
          ignoredActions: [
            reduxSagaFunction.type
          ],
        },
      }),
      sagaMiddleware,
    ],

    
    reducer: rootReducer,
  });
  sagaMiddleware.run(sagas);
  return store;
}

My IDE is telling me that getDefaultMiddleware is deprecated. I have a feeling this is why the behavior isn't as we expect. However, I have not been able to figure out how to rewrite this with the new version of Redux. I have tried changing it to the following but I am experiencing the same behavior:

function getStore(preloadedState) {
  const sagaMiddleware = createSagaMiddleware();
  const store = configureStore({
    preloadedState: preloadedState,

    middleware: (getDefaultMiddleware) =>
      getDefaultMiddleware({
        thunk: false,
        serializableCheck: {
          ignoredActions: [
            reduxSagaFunction.type
          ],
        },
      }).concat(sagaMiddleware),

    reducer: rootReducer,
  });

  sagaMiddleware.run(sagas);
  return store;
}
0

There are 0 answers