Как вызвать функцию загрузки с помощью React useEffect только один раз - PullRequest
0 голосов
/ 02 ноября 2018

Хук useEffect React будет запускать переданную функцию при каждом изменении. Это можно оптимизировать, чтобы он вызывался только при изменении желаемых свойств.

Что, если я хочу вызвать функцию инициализации из componentDidMount и не вызывать ее снова при изменениях? Допустим, я хочу загрузить объект, но функция загрузки не нуждается в данных из компонента. Как мы можем сделать это, используя useEffect крючок?

class MyComponent extends React.PureComponent {
    componentDidMount() {
        loadDataOnlyOnce();
    }
    render() { ... }
}

С крючками это может выглядеть так:

function MyComponent() {
    useEffect(() => {
        loadDataOnlyOnce(); // this will fire on every change :(
    }, [...???]);
    return (...);
}

Ответы [ 4 ]

0 голосов
/ 26 июня 2019

useMountEffect hook

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

const useMountEffect = (fun) => useEffect(fun, [])

Используйте его в любом функциональном компоненте.

function MyComponent() {
    useMountEffect(function) // function will run only once after it has mounted. 
    return <div>...</div>;
}

О хуке useMountEffect

При использовании useEffect со вторым аргументом массива React будет запускать обратный вызов после монтирования (начального рендеринга) и после изменения значений в массиве. Поскольку мы передаем пустой массив, он будет работать только после монтирования.

0 голосов
/ 12 ноября 2018

Передать пустой массив в качестве второго аргумента useEffect. Это эффективно говорит React, цитируя docs :

Это говорит React, что ваш эффект не зависит от каких-либо значений из реквизита или состояния, поэтому его не нужно повторно запускать.

Вот фрагмент, который вы можете запустить, чтобы показать, что он работает:

function App() {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    fetch('https://randomuser.me/api/')
      .then(results => results.json())
      .then(data => {
        setUser(data.results[0]);
      });
  }, []); // Pass empty array to only run once on mount.
  
  return <div>
    {user ? user.name.first : 'Loading...'}
  </div>;
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>
0 голосов
/ 02 апреля 2019

TL; DR

useEffect(yourCallback, []) - вызов будет вызываться только после первого рендера.

Подробное объяснение

useEffect запускается по умолчанию после каждого рендеринга компонента (таким образом вызывая эффект).

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

Если вы передадите только обратный вызов - обратный вызов будет выполняться после каждого рендеринга.

При передаче второго аргумента (массива) React будет запускать обратный вызов после первого рендеринга и каждый раз, когда один из элементов в массиве изменяется. например, при размещении useEffect(() => console.log('hello'), [someVar, someOtherVar]) - обратный вызов будет выполняться после первого рендеринга и после любого рендеринга, что один из someVar или someOtherVar будет изменен.

Передавая второй аргумент пустой массив, React будет сравнивать после каждого рендеринга массив и будет видеть, что ничего не изменилось, вызывая обратный вызов только после первого рендеринга.

0 голосов
/ 02 ноября 2018

Если вы хотите запустить только функцию, заданную useEffect после первоначального рендеринга, вы можете дать ей пустой массив в качестве второго аргумента.

function MyComponent() {
  useEffect(() => {
    loadDataOnlyOnce();
  }, []);

  return <div> {/* ... */} </div>;
}
...