1. ホーム
  2. javascript

[解決済み] ReactのuseCallback/useMemoは何をするのですか?

2023-07-01 20:02:09

質問

で述べたように ドキュメント , useCallback メモ化されたコールバックを返す。

インラインコールバックと入力の配列を渡します。 useCallback は、入力のいずれかが変更された場合にのみ変更される、コールバックのメモ化されたバージョンを返します。これは、不要なレンダリングを防ぐために参照の等価性に依存する最適化された子コンポーネントにコールバックを渡すときに便利です (例: shouldComponentUpdate)。

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

しかし、Reactではどのように動作し、どこで使うのがベストなのでしょうか?

追伸:私は コードペンの例 で視覚化すると、より理解しやすくなると思います。 ドキュメントで説明 .

どのように解決するのですか?

不要な再描画を防ぎ、パフォーマンスを向上させたい場合に使用します。

から取得した子コンポーネントにコールバックを渡す 2 つの方法を比較してみましょう。 React Docs :

1. レンダリングにおける矢印機能

class Foo extends Component {
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={() => this.handleClick()}>Click Me</Button>;
  }
}

2. コンストラクタでのバインド(ES2015)

class Foo extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    console.log('Click happened');
  }
  render() {
    return <Button onClick={this.handleClick}>Click Me</Button>;
  }
}

仮定の話 <Button> が実装されているとすると PureComponent として実装された場合、最初の方法では <Button> が再レンダリングするたびに <Foo> で新しい関数が作成されるため、再レンダリングが行われます。 render() の呼び出しごとに新しい関数が作られるからです。二つ目の方法では handleClick メソッドが一度だけ作成され <Foo> のコンストラクタで一度だけ作成され、レンダリング中に再利用されます。

両方のアプローチをフックを使用する機能的なコンポーネントに変換すると、これらは等価です (一種の)。

1. レンダーでの矢印関数 -> 非メモ化コールバック

function Foo() {
  const handleClick = () => {
    console.log('Click happened');
  }
  return <Button onClick={handleClick}>Click Me</Button>;
}

2. コンストラクタでのバインド (ES2015) -> メモ化されたコールバック

function Foo() {
  const memoizedHandleClick = useCallback(
    () => console.log('Click happened'), [],
  ); // Tells React to memoize regardless of arguments.
  return <Button onClick={memoizedHandleClick}>Click Me</Button>;
}

最初の方法では、機能コンポーネントを呼び出すたびにコールバックが作成されますが、2番目の方法では、Reactがコールバック関数をメモしてくれるので、コールバックが複数回作成されることはありません。

したがって、最初のケースで Button を使って実装した場合 React.memo を使用すると、常に再レンダリングされます(何らかのカスタム比較関数がある場合を除く)。 onClick prop は毎回異なるため、(何らかのカスタム比較関数がない限り) 再レンダリングされます。

ほとんどの場合、最初の方法で問題ありません。Reactのドキュメントにも書いてある通りです。

レンダーメソッドでarrow関数を使用しても良いですか?一般的には コールバック関数にパラメータを渡す最も簡単な方法であることがよくあります。 コールバック関数にパラメータを渡す最も簡単な方法です。

パフォーマンスの問題がある場合は、ぜひとも最適化してください。