Redux-toolkit — состояние обновлено, но при его использовании все еще получается начальное значение состояния

Я уже довольно давно пытаюсь решить проблему, описанную ниже, но так и не смог понять, в чем дело.

Я отправляю действие из своего компонента, и состояние обновляется, что подтверждается его регистрацией в действии. Однако когда я пытаюсь получить доступ к значению состояния сразу после отправки действия, оно все равно показывает начальное значение состояния.

Пожалуйста, взгляните на приведенный ниже код.

сущностьSlice.js

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

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

Редактор.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.info(entityData1);
      },
         function (error) {
            console.info(error);
         }
      );
   };
}

Я получаю правильный ответ от API, и значение состояния меняется, как и ожидалось, когда я проверяю его с помощью console.info(state.entityAttributes);. Однако когда я проверяю данные с помощью console.info(entityData1);, я все равно вижу начальное значение состояния, а не обновленное. Будем очень признательны за любые подсказки о том, как это исправить.

Спасибо

🤔 А знаете ли вы, что...
С помощью JavaScript можно валидировать данные на стороне клиента, что улучшает пользовательский опыт.


80
2

Ответы:

Как я сказал в своем комментарии, проблема связана с тем, что JavaScript фиксирует значения в хранилище Redux во время последнего рендеринга, что означает, что он не получает обновленные значения. Я также был неправ в том, что пропустил, что вы не возвращаете новое состояние или объект полезной нагрузки, что означает, что он не установлен. Вот исправление, которое я сделал, обратите внимание, что я сделал его на TypeScript, потому что это имеет больше смысла, сдержанно предвзято, и я использовал некоторые макетные данные, так как не хотел запускать для него какой-то случайный бэкэнд.

App.tsx — ваш 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.info(store.getState().entity);
            },
            function (error) {
                console.info(error);
            }
        );
    };

    return <div></div>;
};

export default App;

EntitySlice.ts — ваш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;

С этой настройкой у меня все сработало. Надеюсь, это поможет, в противном случае просто оставьте комментарий, а я еще раз посмотрю и отредактирую свой ответ :-)


Решено

В вашем коде есть одна проблема и одно недоразумение.

Основная проблема заключается в том, что вы переназначаете переменную state в своем редукторе. Это то, что Redux Toolkit не может обнаружить (он может обнаруживать только мутации переменной state), вместо этого вам нужно вернуть новое состояние (как описано здесь и здесь).

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

Недоразумение заключается в том, что следующий фрагмент кода будет регистрировать новые данные:

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

Это невозможно. В Javascript вызовы функций (например, вызов dispatch) не могут переназначать локальные переменные вызывающей функции, поэтому entityData1 не может быть другим сразу после dispatch. Однако произойдет следующее: React запланирует повторную отрисовку компонента, а это означает, что ваш компонент будет вызван еще раз, на этот раз с новыми данными. Поэтому вам следует поместить console.info(entityData1) прямо в тело компонента, если вы хотите, чтобы он изменился.