Автор оригинала: Mohammed El Hossiny Riaad.
Useffect
Крюк дает вам лучший способ подумать о вашем жизненном цикле.
С Useffect
, вы можете обрабатывать события жизненного цикла непосредственно внутри функциональных компонентов. А именно три из них: ComponentDidmount
, ComponentDidupdate
и ComponentWillunmount
Отказ Все с одной функцией! Сумасшедший, я знаю. Давайте посмотрим пример.
import React, { useEffect, useState } from 'react'; import ReactDOM from 'react-dom'; function LifecycleDemo() { useEffect(() => { console.log('render!'); return () => console.log('unmounting...'); }) return "I'm a lifecycle demo"; } function App() { const [random, setRandom] = useState(Math.random()); const [mounted, setMounted] = useState(true); const reRender = () => setRandom(Math.random()); const toggle = () => setMounted(!mounted); return ( <> {mounted &&} ); } ReactDOM.render( , document.querySelector('#root'));
Нажмите кнопку «Показать/скрыть». Посмотрите на консоль. Он печатает «размонтирование», прежде чем исчезнет, и «рендеринг!» когда он появляется в пояснице.
Теперь попробуйте кнопку RE-RENDER. С каждым кликом он печатает «рендеринг!» и Он печатает «ramenting». Это кажется странным …
Почему это «размонтирование» с каждым визуалом?
Ну, функция очистки вы можете (необязательно) возврата от Useffect
не Только Вызывается, когда компонент не размонтируется. Это вызывается каждый раз, прежде чем этот эффект работает – чтобы очистить от последнего запуска. Это на самом деле более мощно, чем ComponentWillunmount
Жизненный цикл, потому что он позволяет управлять побочным эффектом до и после каждого рендера, если вам нужно.
Не совсем жизненные циклы
Useffect
Запускается после каждого визуализации (по умолчанию) и может необязательно очистить для себя, прежде чем он запускается снова.
Вместо того, чтобы думать о Useffect
В качестве одной функции выполняют работу 3 отдельных жизненного жизненного циклов, это может быть более полезным думать об этом просто как способ запустить побочные эффекты после рендера – включая потенциальную очистку, которую вы хотите сделать перед каждым, а перед размножением.
Предотвратить работу с использованием каждого визуализации
Если вы хотите, чтобы ваши эффекты могли запускать реже, вы можете предоставить второй аргумент – массив значений. Думать о них как зависимости для этого эффекта. Если один из зависимостей изменился с последнего времени, эффект снова запустится. (Это также все еще будет работать после первоначального визуализации)
const [value, setValue] = useState('initial'); useEffect(() => { console.log(value); }, [value])
Другой способ подумать об этом массиве: он должен содержать каждую переменную, что функция эффекта использует из окружающей массы. Так что, если он использует опоры? Который идет в массиве. Если он использует часть государства? Который идет в массиве.
Только бегать на горе и размонтировать
Вы можете пройти специальное значение Пустой массив []
Как способ сказать «бегать только на горе и размонтировать». Так что, если мы изменили наш компонент выше, чтобы позвонить Useffect
как это:
useEffect(() => { console.log('mounted'); return () => console.log('unmounting...'); }, [])
Затем он будет печать «установлен» после первоначального визуализации, молчать на протяжении всей жизни, и напечатайте «Размонтирование …» на выходе.
Это поставляется с большим предупреждением, хотя: прохождение пустого массива склонна к ошибкам. Легко забыть добавить элемент к нему, если вы добавите зависимость, и если вы Мисс зависимость, то это значение будет устаревшим в следующий раз Useffect
работает, и это может вызвать некоторые странные проблемы.
Сосредоточиться на мосте
Иногда вы просто хотите сделать одна крошечная вещь В Mount Time, и делать то, что одна маленькая вещь требует перезаписи функции в качестве класса.
В этом примере давайте посмотрим, как вы можете сосредоточить входное управление на первом рендере, используя Useffect
в сочетании с УСЭРЕФ
крюк.
import React, { useEffect, useState, useRef } from "react"; import ReactDOM from "react-dom"; function App() { const inputRef = useRef(); const [value, setValue] = useState(""); useEffect( () => { console.log("render"); }, [inputRef] ); return ( setValue(e.target.value)} /> ); } ReactDOM.render(, document.querySelector("#root"));
Наверх, мы создаем пустую ссылку с УСЭРЕФ
Отказ Передача его на вход Ref
Опора позаботится о настройке его после отображения домена. И главное, стоимость возвращена УСЭРЕФ
Будет стабильным между рендурами – это не изменится.
Так что, хотя мы проходим [inputref]
Как 2-й аргумент Useffect
Он будет эффективно работать только один раз, на начальном креплении. Это в основном «ComponentDIDMount» (кроме времени его, которое мы поговорим позже).
Получить данные с использованием
Давайте посмотрим на другой общий корпус использования: привлечь данные и отображение его. В классовом компонент вы бы поставили этот код в ComponentDidmount
метод. Чтобы сделать это с крючками, мы будем тянуть Useffect
Отказ Нам также понадобится Уместите
хранить данные.
Стоит отметить, что при получении Data-Parting Portion of React Intevense Happy Happy готова, это будет предпочтительным способом получения данных. Забрать из Useffect
Имеет одну большую Готчу (которое мы перейдем к), и API ожидания будет намного проще в использовании.
Вот компонент, который выбирает посты из Reddit и отображает их:
import React, { useEffect, useState } from "react"; import ReactDOM from "react-dom"; function Reddit() { const [posts, setPosts] = useState([]); useEffect(() => { async function fetchData() { const res = await fetch( "https://www.reddit.com/r/reactjs.json" ); const json = await res.json(); setPosts(json.data.children.map(c => c.data)); } fetchData(); }); return (
- {posts.map(post => (
- {post.title} ))}
Вы заметите, что мы не передаем второй аргумент на Useffect
здесь. Это плохо. Не делай этого.
Передача 2-го аргумента приводит к тому, что Useffect
Чтобы запустить каждый визуализацию. Затем, когда он работает, это выбирает данные и Обновления штата Отказ Затем, как только состояние будет обновлено, компонент повторно рендерирует, которые вызывают Useffect
очередной раз. Вы можете увидеть проблему.
Чтобы исправить это, нам нужно пройти массив в качестве 2-го аргумента. Что должно быть в массиве?
Давай, подумайте об этом на секунду.
…
…
Единственная переменная, которую Useffect
зависит от этого SetPosts
Отказ Поэтому мы должны пройти массив [SetPosts]
здесь. Потому что SetPosts
Возвращенный сетчик Уместите
, это не будет воссоздано каждый визуализация, и поэтому эффект будет работать только один раз.
Забавный факт: когда вы звоните Уместите
Функция сеттера возвращается только один раз! Это будет точно такой же функциональный экземпляр каждый раз, когда компонент рендерирует, поэтому это безопасно, чтобы эффект зависеть от одного. Этот забавный факт также правда для Отправка
Функция возвращена Успеведщик
Отказ
Повторно привлечься при изменении данных
Давайте расширемся на примере, чтобы охватить другую распространенную проблему: как повторно получить данные, когда что-то изменяется, например, идентификатор пользователя, или в этом случае, имя подстрадателя.
Сначала мы изменим Reddit
Компонент для приема subreddit в качестве опоры, извлеките данные на основе этого подчиненногоdit, и только повторно запустите эффект при изменении опор:
function Reddit({ subreddit }) { const [posts, setPosts] = useState([]); useEffect(() => { async function fetchData() { const res = await fetch( `https://www.reddit.com/r/${subreddit}.json` ); const json = await res.json(); setPosts(json.data.children.map(c => c.data)); } fetchData(); }, [subreddit, setPosts]); return (
- {posts.map(post => (
- {post.title} ))}
Это все еще жестко закодировано, но теперь мы можем настроить его, упаковывая Reddit
Компонент с тем, который позволяет нам изменять подчиненный. Добавьте этот новый компонент приложения и визуализируйте его внизу:
function App() { const [inputValue, setValue] = useState("reactjs"); const [subreddit, setSubreddit] = useState(inputValue); const handleSubmit = e => { e.preventDefault(); setSubreddit(inputValue); }; return ( <>
Приложение удерживает 2 штуки состояния здесь – текущее входное значение и текущий подсадчик. Отправка ввода «комбинирует» подпудрит, что приведет к тому, что выведет Reddit
Чтобы повторно получить данные из нового выбора. Оборачивая вход в форме позволяет пользователю нажать Enter для отправки.
BTW: Тип внимательно. Там нет ошибок. Если вы вводите подсадку, который не существует, приложение взорвется. Реализация обработки ошибок было бы большим упражнением, хотя! 😉.
Мы могли бы использовать только 1 кусочек состояния здесь – хранить вход и отправить то же значение до Reddit
– но тогда Reddit
Компонент будет получать данные с каждым ключом.
Уместите
На вершине может выглядеть немного странно, особенно вторая строка:
const [inputValue, setValue] = useState("reactjs"); const [subreddit, setSubreddit] = useState(inputValue);
Мы передаем первоначальное значение «REVENTJS» на первую часть государства, и это имеет смысл. Это значение никогда не изменится.
Но как насчет этой второй линии? Что если начальное состояние изменения ? (И это будет, когда вы введете в коробку)
Помните, что Уместите
является штатом ( Подробнее о usestate ). Он использует только начальное состояние Однажды , первый раз оно делает. После этого он игнорируется. Так что безопасно пройти переходное значение, как опоры, который может измениться или какая-то другая переменная.
Сто и одно использование
Useffect
Функция похожа на швейцарский армейский нож крючков. Его можно использовать для тонны вещей, от настройки подписок для создания и очистки таймеров для изменения значения REF.
Одна вещь, это не Хорошо для того, чтобы сделать изменения DOM, которые видны пользователю. Способ работы сроки, функция эффекта будет только огонь после Браузер выполняется с помощью макета и краски – слишком поздно, если вы хотите сделать визуальные изменения.
Для тех случаев реагирование обеспечивает Usemtioneffect
и Uselayouteffect
крючки, которые работают так же, как Useffect
кроме того, когда они уволились. Посмотрите на Документы для Use Effect И, в частности, раздел на Сроки эффектов Если вам нужно сделать видимые изменения DOM.
Это может показаться дополнительным осложнением. Еще одна вещь, чтобы беспокоиться. Это вроде, к сожалению. Положительный побочный эффект этого (хе) в том, что с Useffect
Запускается после макета и краски, медленный эффект не сделает janky ui. Внизу – это то, что если вы двигаетесь старого кода из жизненных кругов к крючкам, вы должны быть немного осторожны, так как это означает Useffect
почти – но не совсем эквивалентно ComponentDidupdate
в отношении времени.