Когда и зачем использовать эффект - PullRequest
4 голосов
/ 26 января 2020

Это может показаться странным вопросом, но я на самом деле не вижу много вариантов использования для useEffect в React (в настоящее время я работаю над базой кода React из нескольких тысяч строк и никогда не использовал ее один раз), и я думаю, что может быть что-то, что я не в полной мере gr asp.

Если вы пишете функциональный компонент, какая разница, если вы помещаете ваш код эффекта в хук useEffect вместо простого выполнения это в теле функционального компонента (который также выполняется при каждом рендеринге)?

Типичным вариантом использования будет выборка данных при монтировании компонента: я вижу два подхода к этому, один с useEffect и один без:

// without useEffect
const MyComponent = () => {
    [data, setData] = useState();
    if (!data) fetchDataFromAPI().then(res => setData(res));

    return(
        {data ? <div>{data}</div> : <div>Loading...</div>}
    )
}
// with useEffect
const MyComponent = () => {
    [data, setData] = useState();
    useEffect(() => {
    fetchDataFromAPI().then(res => setData(res))
    }, []);

    return(
        {data ? <div>{data}</div> : <div>Loading...</div>}
    )
}

Есть ли преимущество (с точки зрения производительности или другое) для useEffect в таких случаях использования?

Ответы [ 3 ]

1 голос
/ 26 января 2020

I. Очистка

Что если ваш компонент будет уничтожен до завершения выборки? Вы получаете ошибку.

useEffect предоставляет простой способ очистки возвращаемого значения обработчика.

II. Реакции на изменение реквизита.

Что если у вас есть userId, переданный в реквизит, который вы используете для извлечения данных. Без useEffect вам придется дублировать userId в состоянии, чтобы можно было определить, изменилось ли оно, и вы сможете получить новые данные.

1 голос
/ 26 января 2020

Дело в том, что useEffect выполняется не при каждом рендеринге.

Чтобы увидеть это более четко, давайте предположим, что ваш компонент MyComponent визуализируется родительским компонентом (давайте назовите его ParentComponent) и он получит реквизит от этого родительского компонента, который может измениться от действия пользователя.

ParentComponent

const ParentComponent = () => {
    const [ counter, setCounter ] = useState(0);
    const onButtonClicked = () => setCounter(counter + 1);

    return (
        <>
            <button onClick={onButtonClicked}>Click me!</button>
            <MyComponent counter={counter} />
        </>
    );
}

И ваш MyComponent (слегка изменено для чтения и использования counter prop):

const MyComponent = ({ counter }) => {
    [data, setData] = useState();

    useEffect(() => {
        fetchDataFromAPI().then(res => setData(res))
    }, []);

    return(
        <div>
            <div>{counter}</div>
            {data ? <div>{data}</div> : <div>Loading...</div>}
        </div>
    )
}

Теперь, когда компонент MyComponent монтируется в первый раз, будет выполняться операция выборки. Если впоследствии пользователь нажимает кнопку и счетчик увеличивается, useEffect не будет выполняться (но будет вызвана функция MyComponent для обновления из-за изменения counter)!

Если вы не используете useEffect , когда пользователь нажимает на кнопку, операция выборки будет выполнена снова, поскольку изменилась подпорка счетчика, а метод рендеринга MyComponent казнены.

0 голосов
/ 26 января 2020

useEffect обрабатывает побочный эффект проблемы. useEffect - это комбинация componentDidMount и componentDidUpdate . каждый начальный рендер и всякий раз, когда реквизит обновляется, он будет выполняться.

Для примера:

useEffect(() => {
      fetchDataFromAPI().then(res => setData(res))
}, []);

Другой пример:

Давайте предположим, что у вас есть несколько переменных состояния, компонент будет повторно визуализировать для каждого изменения значений состояния. Но нам может понадобиться запускать useEffect в конкретном c сценарии, а не выполнять его для каждого изменения состояния.

function SimpleUseEffect() {

  let [userCount, setUserCount] = useState(0);
  let [simpleCount, setSimpleCount] = useState(0);

useEffect(() => {
    alert("Component User Count Updated...");
  }, [userCount]);

  useEffect(() => {
    alert("Component Simple Count Updated");
  }, [simpleCount]);

  return (
    <div>
      <b>User Count: {userCount}</b>
      <b>Simple Count: {simpleCount}</b>
      <input type="button" onClick={() => setUserCount(userCount + 1}} value="Add Employee" />
      <input type="button" onClick={() => setSimpleCount(simpleCount + 1}} value="Update Simple Count" />
    </div>
  )
}

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

  1. Выполнение асинхронных вызовов API для данных

  2. Настройка подписка на наблюдаемое

  3. Обновление элемента DOM вручную

  4. Обновление глобальных переменных внутри функции

для более подробной информации смотрите этот блог https://medium.com/better-programming/https-medium-com-mayank-gupta-6-88-react-useeffect-hooks-in-action-2da971cfe83f

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...