Вопрос или проблема
Я использую React-Redux и Redux-Toolkit, и храню состояние как объект в хранилище Redux. При отправке действия я вижу, что целевой ключ объекта и его родитель изменяются в хранилище Redux (по данным Redux-Devtools), но React не перерисовывает целевой компонент и его родителя. Redux-Toolkit использует Immer.js, поэтому я предполагаю, что мутирование полей в объекте вызовет изменение состояния.
import { createSelector, createSlice } from '@reduxjs/toolkit'
import { current } from '@reduxjs/toolkit';
const fooSlice = createSlice({
name: "foo",
initialState : {},
reducers: {
updateStatus(state, action) {
const {tid, newStatus } = action.payload;
const targetNode = state[tid];
targetNode.status = newStatus;
const parent = targetNode.pid;
targetNode.status = newStatus;
},
setData(state, action) {
return {...state, ...action.payload};
}
}
});
export const selectNode = (state, nodeId) => {
return state.foo[nodeId]
};
export const selectStatus = createSelector(
[selectNode],
(node) => {
return node ? node.status : null
}
);
В компоненте
const nodeStatus = selectStatus(state, node.id);
function onChangeHandler(event) {
dispatch(updateStatus({
tid: node.id,
newStatus: event.target.value
}));
}
<span>{nodeStatus}</span>
// в useEffect
// отправка данных от api для обновления начального состояния
dispatch(setData({
'a': { pid: 'b', 'status': 'xxx' },
'b': { 'status': 'xxx' },
'c': {}
}))
Ответ или решение
Проблема, с которой вы столкнулись, заключается в том, что компонент не перерисовывается при изменении состояния дочернего компонента, даже если изменения состояния правильно отражаются в Redux Store. Вот несколько причин, почему это может происходить, и решения для устранения этой проблемы.
1. Проверка правильного использования селекторов
Сначала убедитесь, что вы используете селекторы правильно. В вашем случае вы используете selectStatus
, который зависит от selectNode
. Убедитесь, что selectNode
правильно получает идентификатор узла. Селекторы Redux должны возвращать новые ссылки, когда наблюдаемое состояние изменяется, чтобы React мог определить, что нужно обновить компонент.
2. Избегайте мутаций состояния
Хотя Redux Toolkit использует Immer, и вы можете изменять состояние в редюсерах, убедитесь, что вы не производите мутирующие операции в других местах. Например, если вы изменяете объект состояния вне редюсера и возвращаете его обратно, React не сможет обнаружить изменения.
Обратите внимание на объявление targetNode
в вашем редюсере. Вместо:
const targetNode = state[tid];
targetNode.status = newStatus;
Вы можете сделать это более явно:
state[tid] = {
...state[tid],
status: newStatus,
};
3. Правильное использование dispatch
Обратите внимание на то, как вы вызываете onChangeHandler
. Убедитесь, что dispatch
правильно вызывается, и состояние действительно обновляется. Используйте console.log()
для вывода состояния перед и после вызова dispatch
в updateStatus
.
4. Перерисовка родительского компонента
Если родительский компонент не перерисовывается, убедитесь, что он также использует правильные селекторы и не хранит устаревшие ссылки на состояния. Возможно, вам потребуется следить за состоянием родительского компонента. Если состояние родителя зависит от состояния дочернего компонента, убедитесь, что вы извлекаете его с помощью селектора.
const parentStatus = selectStatus(state, parentId); // Пример получения состояния родителя
5. Использование useSelector
Убедитесь, что в компоненте вы используете useSelector
из react-redux
, чтобы подписаться на изменения состояния. Пример использования:
import { useSelector, useDispatch } from 'react-redux';
const YourComponent = ({ nodeId }) => {
const dispatch = useDispatch();
const nodeStatus = useSelector((state) => selectStatus(state, nodeId));
function onChangeHandler(event) {
dispatch(updateStatus({
tid: nodeId,
newStatus: event.target.value
}));
}
return <span>{nodeStatus}</span>;
};
Заключение
Ваша проблема в том, что компонент не обновляется, может быть связана с неправильным извлечением данных с помощью селекторов, мутациями состояния или отсутствием подписки на изменения состояния. Проверьте вышеуказанные аспекты и скорректируйте код, чтобы обеспечить правильное выполнение всех указанных пунктов. Если все сделано правильно, измененное состояние должно автоматически приводить к обновлению компонента.