skip to Main Content

I have been trying to solve the issue below for quite some time but haven’t been able to figure out what is wrong.

I am dispatching an action from my component, and the state is getting updated, as confirmed by logging it in the action. However, when I try to access the value of the state immediately after dispatching the action, it still shows the initial state value.

Please have a look at the below code.

entitySlice.js

export const entitySlice = createSlice({
    name: 'entity',
    initialState,
    reducers: {
        setEntity: (state, action) => {
            state = action.payload;
            console.log(state.entityAttributes);
        },
    },
});

export const { setEntity } = entitySlice.actions;
export default entitySlice.reducer;

Editor.jsx

const EntityEditor = () => {
   const effectRan = useRef(false);
   const [searchParams] = useSearchParams();
   const dispatch = useDispatch();
   const entityData1 = useSelector((state) => state.entity);

   useEffect(() => {
      if (!effectRan.current) {
         effectRan.current = true;
         getEntityData();
      }
   });

   const getEntityData = () => {
      entityOperations.getEntity(searchParams.get("PK_Entity")).then(function (response) {
         dispatch(setEntity(response));
         console.log(entityData1);
      },
         function (error) {
            console.log(error);
         }
      );
   };
}

I am getting the correct response from the API, and the state value is changing as expected when I check it using console.log(state.entityAttributes);. However, when I check the data using console.log(entityData1);, I still see the initial state value, not the updated one. Any pointers on how to fix this would be greatly appreciated.

Thanks

2

Answers


  1. As I said in my comment the issue is related to the fact that React sometimes captures the values in the Redux store during the last render which means that it doesn’t get the updated values. I was also wrong in that I missed that you don’t return the new state or payload entity which means that it isn’t being set. Here is a fix I made, note that I made it in TypeScript cause it makes more sense, lowkey biased, and I used some mock data since I didn’t want to spin up some random backend for it.

    App.tsx, which is your Editor.jsx

    import { useRef, useEffect } from 'react';
    import { getMockData } from './MockData';
    import { useDispatch } from 'react-redux';
    import { setEntity } from './Redux/EntitySlice';
    import store from './Redux/store';
    
    const App = () => {
        const effectRan = useRef(false);
        const dispatch = useDispatch();
    
        useEffect(() => {
            if (!effectRan.current) {
                effectRan.current = true;
                getEntityData();
            }
        });
    
        const getEntityData = () => {
            getMockData().then(
                function (response) {
                    dispatch(setEntity(response));
                    console.log(store.getState().entity);
                },
                function (error) {
                    console.log(error);
                }
            );
        };
    
        return <div></div>;
    };
    
    export default App;
    

    EntitySlice.ts, which is your entitySlice.js

    import { PayloadAction, createSlice } from '@reduxjs/toolkit';
    import { card } from '../MockData';
    
    const initialState: card[] = [];
    
    export const entitySlice = createSlice({
        name: 'entity',
        initialState,
        reducers: {
            setEntity: (_, action: PayloadAction<card[]>) => {
                return action.payload;
            },
        },
    });
    
    export const { setEntity } = entitySlice.actions;
    export default entitySlice.reducer;
    

    With this setup it worked for me. Hope it helps, otherwise just make a comment and I take another look and edit my answer 🙂

    Login or Signup to reply.
  2. There is one problem and one misunderstanding in your code.

    The main issue is that you are reassigning to the state variable in your reducer. This is something that cannot be detected by Redux Toolkit (it can only detect mutations to the state variable), you need instead to return the new state (as documented here and here).

    // state = action.payload; // Incorrect
    return action.payload; // Correct
    

    The misunderstanding is that the following piece of code will log the new data:

    dispatch(setEntity(response));
    console.log(entityData1);
    

    This is not possible. In Javascript, function calls (like the call to dispatch) cannot reassign local variables of the calling function, so entityData1 cannot possibly be different just after the dispatch. What will happen, however, is that React will schedule a rerender of the component, which means that your component will be called one more time, this time with the new data. So you should put your console.log(entityData1) directly in the body of the component if you want to see it change.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search