Как мы можем реализовать componentWillUnmount, используя реакционные хуки? - PullRequest
4 голосов
/ 21 апреля 2019

Метод componentWillUnmount() вызывается немедленно до компонента демонтируется и уничтожается. Если мы используем useEffect с пустым массивом ([]) в качестве второго аргумента и поместим нашу функцию в оператор return, она будет выполнена после размонтирования компонента и даже после монтирования другого компонента. Насколько я понимаю, это сделано из соображений производительности. Чтобы не задерживать рендеринг.

Итак, вопрос в том, как мы можем вызвать некоторую функцию, используя ловушки, прежде чем компонент будет размонтирован?

То, что я пытаюсь сделать, - это приложение, которое сохраняет ввод пользователя при вводе (без отправки формы). Я использую setInterval для сохранения обновленного текста каждые N секунд. И мне нужно принудительно сохранить обновления, прежде чем компонент будет размонтирован. Я не хочу использовать запрос по маршрутизатору перед навигацией. Это электронное приложение. Я ценю любые мысли или советы о том, как реализовать такую ​​функциональность.

Обновление

К сожалению, Эффекты с очисткой запускаются после того, как браузер нарисовал. Более подробную информацию можно найти здесь: А как насчет очистки? . В основном это означает, что очистка запускается после размонтирования компонента, и это не то же самое, что выполнение кода в componentWillUnmount(). Я ясно вижу последовательность вызовов, если я помещаю операторы console.log в код очистки и в другой компонент. Вопрос в том, можем ли мы выполнить некоторый код до того, как компонент будет размонтирован с использованием хуков.

Update2

Как я вижу, я должен лучше описать мой вариант использования. Давайте представим теоретическое приложение, которое хранит свои данные в магазине Redux. И у нас есть два компонента с некоторыми формами. Для простоты у нас нет ни бэкенда, ни асинхронной логики. В качестве хранилища данных мы используем только хранилище Redux.

Мы не хотим обновлять магазин Redux при каждом нажатии клавиши. Таким образом, мы сохраняем фактические значения в состоянии локального компонента, которое мы инициализируем значениями из хранилища, когда компонент монтируется. Мы также создаем эффект, который устанавливает setInterval для 1 с.

У нас есть следующий процесс. Пользователь что-то печатает. Обновления хранятся в состоянии локального компонента, пока не будет вызван наш обратный вызов setInterval. Обратный вызов просто помещает данные в хранилище (отправляет действие). Мы помещаем наш обратный вызов в оператор возврата useEffect, чтобы принудительно сохранить сохранение, когда компонент отключается, потому что мы хотим сохранить данные для сохранения в этом случае как можно скорее.

Проблема возникает, когда пользователь вводит что-то в первый компонент и сразу переходит ко второму компоненту (быстрее, чем 1 с). Так как очистка в нашем первом компоненте будет вызвана после повторного рендеринга, наше хранилище не будет обновлено, пока не будет смонтирован второй компонент. И поэтому второй компонент получит устаревшие значения в своем локальном состоянии.

Если мы поместим наш обратный вызов в componentWillUnmount(), он будет вызван перед размонтированием, и хранилище будет обновлено до монтирования следующего компонента. Так можем ли мы реализовать это с помощью хуков?

Ответы [ 3 ]

5 голосов
/ 21 апреля 2019

componentWillUnmount можно смоделировать, возвращая функцию внутри хука useEffect.Возвращенная функция будет вызываться непосредственно перед каждым повторным рендерингом компонента.Строго говоря, это то же самое, но вы должны иметь возможность имитировать любое поведение, которое вы хотите, используя это.

useEffect(() => {
  const unsubscribe = api.createSubscription()
  return () => unsubscribe()
})

Более подробное объяснение этого вопроса см. Здесь здесь .

1 голос
/ 23 апреля 2019

Неважно, будет ли возвращенная функция из useEffect вызываться до или после размонтирования компонента: у вас все еще есть доступ к значениям состояний через замыкание:

  const [input, setInput] = useState(() => Store.retrieveInput());

  useEffect(() => {
    return () => Store.storeInput(input); // < you can access "input" here, even if the component unmounted already
  }, []);

Если вы этого не сделаетеуправляйте вводом в состоянии компонентов, вся ваша структура нарушена и должна быть изменена для управления состоянием в нужном месте.В вашем случае вы должны поднять состояние общего входа компонентов на родительский.

0 голосов
/ 23 апреля 2019

Документы ReactJS на хуках определяют это:

Эффекты также могут дополнительно указывать, как «очистить» их, возвращая функцию.

Так что любая функция, которую выreturn в вашем useEffect хуке, будет выполнен при размонтировании компонента, а также до повторного запуска эффекта из-за последующего рендеринга.

...