#reactjs #redux #middleware
#reactjs #redux #промежуточное программное обеспечение
Вопрос:
Описание
У меня есть компонент, который показывает данные, которые поступают с сервера, и отображает их в таблице, используя состояние, tableData, и оно должно быть установлено при отправке действия Redux.
Я использую библиотеку прослушивателя действий, которая использует Redux middleware
which, состоящую из 63 строк кода. redux-слушатели-qkreltms.
Например, когда я регистрирую функцию, для analysisListIsReady({}).type
которой ANALYSISLIST_IS_READY
затем отправляется действие, вызывается функция.
Проблема
Проблема в том, что react иногда выдает ошибку: Can't update react state...
для setTableData
so данные ответа игнорируются для установки. Я хочу выяснить это, когда это произойдет.
Я предположил, что это из-за размонтирования компонента, поэтому я напечатал несколько журналов, но ни один из журналов не напечатан, а также ComponentA не исчез.
При удалении и не возникает никаких ошибок getAnalysisJsonPathApi
getResource
, поэтому я попытался сообщить об этом, но не удалось … ссылка
При удалении не возникает никаких ошибок listenMiddleware.addListener
, см.: # 2
#1
// ComponentA
const [tableData, setTableData] = useState([])
useEffect(() => {
return () => {
console.log("unmounted1")
}}, [])
useEffect(() => {
listenMiddleware.addListener(analysisListIsReady({}).type, (_) => {
try {
getAnalysisJsonPathApi().then((res) => {
//...
getResource(volumeUrl)
.then((data: any) => {
// ...
setTableData(data)
})
})
} catch (error) {
warn(error.message)
}
})
return () => {
console.log("unmounted2")
}
}, [])
export const getAnalysisJsonPathApi = () => {
return api
.post('/segment/volume')
.then(({ data }) => data)
export const getResource = async (src: string, isImage?: boolean): Promise<ArrayBuffer> =>
api
.get(src)
.then(({ data }) => data)
#2
// ComponentA
const [tableData, setTableData] = useState([])
useEffect(() => {
return () => {
console.log("unmounted1")
}}, [])
useEffect(() => {
if (steps.step2a) {
try {
getAnalysisJsonPathApi().then((res) => {
//...
getResource(volumeUrl)
.then((data: any) => {
// ...
setTableData(data)
})
})
} catch (error) {
warn(error.message)
}
}
return () => {
console.log("unmounted2")
}
}, [steps.step2a])
Ответ №1:
Ну, как вы сказали:
из-за размонтирования компонента
В вашей UseEffect()
функции вам нужно проверить, смонтирована ли компонентная сеть или нет, другими словами, вам нужно выполнить componentDidMount
логику amp; componentDidUpdate
(при необходимости):
const mounted = useRef();
useEffect(() => {
if (!mounted.current) {
// do componentDidMount logic
console.log('componentDidMount');
mounted.current = true;
} else {
// do componentDidUpdate logic
console.log('componentDidUpdate');
}
});
Ответ №2:
я не вдавался в подробности кода вашего вопроса, но моя подсказка может вам помочь, обычно эта ошибка возникает в функции fetchData, предположим, у вас есть функция fetchData, как показано ниже:
fetchData(){
...
let call = await service.getData();
...
--->setState(newItems)//Here
}
поэтому, когда требуется обновить конец и состояние вызова api, если компонент был размонтирован, состояние не устанавливается,
вы можете использовать переменную bool и установить ее false, когда компонент будет размонтирован:
let stillActive= true;
fetchData(){
active = true;
...
let call = await service.getData();
...
if(stillActive)
setState(newItems)//Here
}
}
componentWillUnmount(){
active = false;
}
Ответ №3:
Я узнал, что это из-за redux-listeners-qkreltms, Redux промежуточного программного обеспечения.
Он сохраняет функцию, когда компонент монтируется в прослушиватель, но никогда не изменяет свои функции, даже если компонент размонтирован.
middleware.addListener = (type, listener) => {
for (let i = 0; i < listeners.length; i = 1) {
if (listeners[i].type === type) {
return;
}
}
listeners.push(createListener(type, listener));
};