#javascript #reactjs #react-hooks #frontend
Вопрос:
Реакция выдает ошибку, когда мы пытаемся обновить состояние размонтированного компонента.Поэтому, когда я тестирую компонент react на это, я получаю ошибки только при первом рендеринге.
Я создал компонент, который включает дочерний компонент на основе щелчка. И у дочернего компонента есть кнопка, которая обновляет состояние после некоторого settimeout, которая выдает предупреждение о реакции
Предупреждение: Не удается выполнить обновление состояния реакции для размонтированного компонента. Это не операция, но это указывает на утечку памяти в вашем приложении. Чтобы исправить это, отмените все подписки и асинхронные задачи в функции очистки useEffect.
Что совершенно справедливо. Но чтобы преодолеть это, я передаю enable props от родительского компонента, основываясь на том, что в дочернем компоненте есть условие непосредственно перед настройкой. Так почему же он выдает ошибку только с первого раза?
Чтобы воспроизвести
Нажмите на кнопку дочернего компонента, которая является false
, и нажмите кнопку родительского компонента enable
, которая размонтирует дочерний компонент.
**Мой вопрос в том, зачем реагировать на ошибку только в первый раз ? И почему это хорошо работает во второй раз **
Родительский компонент
import { useState } from "react";
import "./styles.css";
import { Test } from "./Test";
export default function App() {
const [state, setstate] = useState(true);
const changeState = () => {
setstate(!state);
};
return (
<div className="App">
<button onClick={changeState}>enable </button>
{state amp;amp; <Test enable={state} />}
</div>
);
}
Дочерний компонент
import React, { useState } from "react";
export const Test = (props) => {
const [state, setstate] = useState(false);
const fetchData = () => {
setstate(!state);
if (props.enable) {
setTimeout(() => {
setstate(false);
}, 1000);
}
};
return (
<>
<button onClick={fetchData}> {`${state}`}</button>
</>
);
};
Комментарии:
1. Ошибка на самом деле происходит каждый раз, но React показывает ошибку только один раз, чтобы избежать переполнения консоли множеством повторяющихся сообщений об ошибках.
Ответ №1:
Хороший трек, просто вам не хватает незначительного момента, когда вы пишете состояние, для выполнения которого требуется некоторое время, и в то же время мы можем снова и снова посещать поток, основываясь на любом действии, тогда нам нужно очистить старую подписку, прежде чем перейти к новой…
Например, в вашем коде здесь вы обновляете поток состояний, но поток состояний регистрирует новую подписку каждый раз, когда мы посещаем компонент с допустимыми реквизитами и нажимаем кнопку, чтобы выполнение до запуска все еще работало, когда вы запускаете новое событие, так просто, что нам нужно сделать, размонтировав старую подписку, и мы можем сделать это для вашего случая:
import React, { useState, useEffect } from "react";
export const Test = (props) => {
const [state, setstate] = useState(false);
useEffect(() => {
if (props.enable) {
const timer = setTimeout(() => {
setstate(false);
}, 1000);
return () => clearTimeout(timer);
}
}, [state, props.enable]);
const fetchData = () => {
setstate((prev) => !prev);
};
return (
<>
<button onClick={fetchData}> {`${state}`}</button>
</>
);
};
Посмотрите на код выше, просто мы добавляем код, который нужно очистить, чтобы он выглядел в моем состоянии и поддерживал, теперь, когда я нажимаю на кнопку, эффект сработает, если мы сделаем это снова, clearTime будет работать для предварительной подписки, а затем добавим новую и так далее…
Примечания:
- В вашем случае мы можем удалить функцию и использовать setState непосредственно на вашей кнопке.
- Предпочитаете использовать обратный вызов в своей функции, например
const fetchData = useCAllback...
- Вы можете использовать
setstate((prev) => !prev);
его в качестве моментального снимка, и он полезен, когда вы зависите от старого значения..но, возможно, в некоторых случаях он тоже не нужен, но просто для того, чтобы знать об этой функции.
Обновление 1:
Что такое Подписка:
Вы можете сказать, что подписка представляет собой доступный ресурс, такой как выполнение наблюдаемого. У подписки есть один важный метод, отмена подписки, который не принимает аргументов и просто распоряжается ресурсом, принадлежащим подписке, другими словами, вы можете сказать «да», любая асинхронная задача или любое задание будет вызвано для реагирования на состояние жизненного цикла и его необходимое для наблюдения за изменениями, затем вы говорите о подписке, например, API или тайм-аут или интервал времени и так далее, любое из этих действий, которые необходимо очистить до подписки (остановить наблюдателя — отменить подписку), чтобы предотвратить утечку памяти и очистить память, чтобы сохранить поток состояний в безопасности и предотвратить ненужный повторный запуск.
Комментарии:
1. Происходит ли это из-за отключения времени !! И не могли бы вы, пожалуйста, объяснить, что такое подписка ? Насколько мне известно, вызывающий API, любая асинхронная задача, такая как обещание, является подпиской !!
2. Хороший вопрос, вы можете сказать, что подписка представляет собой одноразовый ресурс, такой как выполнение наблюдаемого. У подписки есть один важный метод, отмена подписки, который не принимает аргументов и просто распоряжается ресурсом, принадлежащим подписке, другими словами, вы можете сказать «да», любая асинхронная задача или любое задание будет вызвано для реагирования на состояние жизненного цикла и его необходимое для наблюдения за изменениями, затем вы говорите о подписке, например, api или тайм-аут или интервал и т. Д., Это необходимо для очистки предварительной подписки (остановить наблюдателя — отменить подписку), чтобы предотвратить утечку памяти и очистить память и сохранить поток состояний в безопасности
3. Основываясь на предыдущем комментарии, мы можем ответить «Происходит ли это из-за setTimeout «, да
4. Начальная настройка времени рендеринга остается в памяти, что является единственной причиной всего этого. Во второй раз в моем коде, если из-за этого условие прекращает выполнение, я не вижу ошибки. Я прав?
5. Да, если вы установите условие для предотвращения этого, проблема будет устранена, так как вы не будете вызывать таймер в память… но угрюмый в вашем случае не является оптимальным решением, хорошим является использование функции очистки react, которая используется в приведенном выше примере.