Реагировать на зависимые от крючка функции в качестве реквизита - PullRequest
0 голосов
/ 14 марта 2019

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

Рассмотрим следующий компонент класса, где ссылка на функцию является связанной функцией, поэтому повторных визуализаций из-за этого не происходит.

import React from 'react';

class Example extends React.Component {
  state = { count: 0 }

  onIncrementClicked = () => setState({ count: this.state.count + 1 })

  render() {
    return (
      <div>
        <p>You clicked {this.state.count} times</p>
        <button onClick={this.onIncrementClicked}>
          Click me
        </button>
      </div>
    );
  }
}

Теперь сравните его с версией hooks, где мы передаем новую функцию при каждом рендеринге кнопке. Если рендеринг <Example /> компонента, нет способа избежать повторного рендеринга его <button /> child.

import React, { useState } from 'react';

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Я знаю, что это небольшой пример, но рассмотрим более крупное приложение, в котором передается множество обратных вызовов, которые зависят от ловушек. Как это можно оптимизировать?

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

1 Ответ

3 голосов
/ 14 марта 2019

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

const handleClick = useCallback(
  () => {
    setCount(count + 1)
  },
  [count],
);

Для лучшей оптимизации вы можете сохранить значение count в качестве атрибута кнопки, чтобы вам не требовался доступ к этой переменной внутри обработчика событий:

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);
  const handleClick = useCallback(
    (e) => setCount(parseInt(e.target.getAttribute('data-count')) + 1),
    []
  );

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick} data-count={count}>
        Click me
      </button>
    </div>
  );
}

Также проверьте https://reactjs.org/docs/hooks-faq.html#are-hooks-slow-because-of-creating-functions-in-render

...