Доступ к предыдущему состоянию в методе useDispatch

Как мне получить доступ к предыдущему состоянию внутри функции обратного вызова в реакции? Потому что, когда я обращаюсь к data, он всегда возвращает исходную версию, так как я использую useEffect только при монтировании.

const data = useSelector(({ state }) => state.data);
const dispatch = useDispatch();

useEffect(_ => {
    dataService.loadData().then(resp => {
        dispatch({ type: 'SET_DATA', payload: resp.data });
    });
}, []);

const addData = newData => {
    dataService.addData(newData).then(_ => {
        // need the up to date state here for data
        dispatch({ type: 'SET_DATA', payload: [newData, ...data] })
    });
}

return <>
    <button onClick = {_ => addData({ name: "new name" })}></button>
    {data.map(elem => <div>{elem.name}</div>)}
</>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
26
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я думаю, вы неправильно думаете о Redux. Вы получаете доступ к «предыдущему» состоянию в функции редуктора. На самом деле это текущее состояние, но функция редьюсера является функцией состояния и действия, то есть (состояние, действие) => nextState.

Функция редуктора — это место для доступа к состоянию, которое вы пытаетесь обновить.

Пример:

const initialState = {
  ... other state properties ...
  data: [],
};

const reducer = (state = initialState, action) => {
  switch(action.type) {
    ... other cases ...

    case SET_DATA:
      return {
        ...state,
        data: [action.payload, ...data],
      }

    default:
      return state;
  }
};

Затем обработчик addData просто отправляет действие с newData в полезной нагрузке.

const addData = newData => {
  dataService.addData(newData)
    .then(_ => {
      dispatch({ type: 'SET_DATA', payload: newData })
    });
};

Если вам нужно различать загрузка для данных и добавление для них в отношении того, как они обрабатываются и обновляют состояние, я предлагаю использовать отдельные типы действий, например SET_DATA и ADD_DATA.

Я полностью с вами согласен, но все же мне интересно, почему data внутри функции обратного вызова всегда равно тому, что в начальном состоянии? Почему это значение не содержит значение актуального состояния?

Lab Lab 07.05.2022 11:14

Что, если мне нужно проверить, содержит ли data некоторые элементы перед обновлением состояния?

Lab Lab 07.05.2022 11:51

Означает ли это, что хуки реакции поддерживают доступ к состоянию только внутри функции dispatch?

Lab Lab 07.05.2022 15:02

@LabLab Возвращает ли всегда исходное значение data или это просто обновление? Из кода, которым вы поделились, не совсем понятно, почему вы можете видеть какие-либо устаревшие вложения поверх data. Если вам нужно проверить, содержит ли data некоторые элементы перед обновлением состояния, вы можете сделать это в редьюсере, где у вас есть как текущее состояние и, так и полезная нагрузка действия. Я не совсем понимаю ваш последний вопрос, но я склонен сказать нет, есть несколько способов получить доступ к состоянию редукции.

Drew Reese 10.05.2022 08:24
Ответ принят как подходящий

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

Хотя это не проблема, если вы используете компонент класса.

Для функциональные компоненты вам нужно использовать функцию dispatch, у которой есть доступ к текущему состоянию. Итак, чтобы правильно обновить мои данные, я использовал следующий код:

const addData = newData => {
    dispatch(addDataDispatch(newData));
}

В вашем редукторе:

export const addDataDispatch = newData => {
   return (dispatch, getState) => {
       const {state: {data}} = getState();
       if (data.includes(newData)) return;
       dataService.addData(newData).then(_ => {
        dispatch({ type: 'SET_DATA', payload: [newData, ...data] })
    });
   }
}

Другие вопросы по теме