Не удается обновить состояние реакции, даже если компонент не размонтирован

#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));
  };