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

Описание

У меня есть компонент, который показывает данные, получаемые с сервера, и отображает их в таблице, используя состояние, tableData, и он должен быть установлен при отправке действия Redux.

Я использую библиотеку прослушивателя действий, которая использует Redux middleware, состоящую из 63 строк кода. redux-listeners-qkreltms.

Например, когда я регистрирую функцию в analysisListIsReady({}).type, которая является ANALYSISLIST_IS_READY, тогда, когда действие отправляется, функция вызывается.

Проблема

Проблема в том, что реакция иногда выдает ошибку: Can't update react state... для setTableData, поэтому данные ответа игнорируются для установки. Я хочу понять, когда это произойдет.

Я предположил, что это из-за размонтирования компонента, поэтому я распечатал несколько журналов, но ни один из журналов не печатается, а также ComponentA не исчез.

При удалении getAnalysisJsonPathApi и getResource не возникает никаких ошибок, поэтому я попытался повторить это, но не удалось... ссылка

При удалении не возникает никаких ошибок listenMiddleware.addListener см.: # 2

#1

// ComponentA
const [tableData, setTableData] = useState([])
useEffect(() => {
  return () => {
    console.info("unmounted1")
}}, [])  

useEffect(() => {
    listenMiddleware.addListener(analysisListIsReady({}).type, (_) => {
      try {
        getAnalysisJsonPathApi().then((res) => {
          //...
          getResource(volumeUrl)
            .then((data: any) => {
              // ...
              setTableData(data)
            })
        })
      } catch (error) {
        warn(error.message)
      }
    })

    return () => {
      console.info("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.info("unmounted1")
}}, [])  

useEffect(() => {
    if (steps.step2a) {
      try {
        getAnalysisJsonPathApi().then((res) => {
          //...
          getResource(volumeUrl)
            .then((data: any) => {
              // ...
              setTableData(data)
            })
        })
      } catch (error) {
        warn(error.message)
      }
    }

    return () => {
      console.info("unmounted2")
    }
  }, [steps.step2a])
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
62
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ну, как ты сказал:

из-за размонтирования компонента

В вашей функции UseEffect() вам нужно проверить, смонтирован ли компонент или нет, другими словами, вам нужно выполнить логику componentDidMount и componentDidUpdate (при необходимости):

const mounted = useRef();

useEffect(() => {
if (!mounted.current) {
    // do componentDidMount logic
    console.info('componentDidMount');
    mounted.current = true;
} else {
    // do componentDidUpdate logic
    console.info('componentDidUpdate');
}
});

я не перешел к коду вашего вопроса, но моя подсказка может вам помочь, обычно эта ошибка возникает в функции fetchData, предположим, что у вас есть функция fetchData, как показано ниже:

fetchData(){
...
let call = await service.getData();
...
--->setState(newItems)//Here
}

поэтому, когда вызов API завершается и требуется обновить состояние, если компонент был размонтирован, состояние для установки не требуется, вы можете использовать логическую переменную и установить ее в false, когда компонент будет размонтирован:

    let stillActive= true;
    
    fetchData(){
    active = true;
    ...
    let call = await service.getData();
    ...
    if (stillActive)
       setState(newItems)//Here
    }
    }

    componentWillUnmount(){
        active = false;
    }
Ответ принят как подходящий

Я узнал, что это из-за 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));
  };

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