Closed10

useRefのdocsを読む

hajimismhajimism

Reference

When you change the ref.current property, React does not re-render your component. React is not aware of when you change it because a ref is a plain JavaScript object.

ref.currentを更新してもre-renderは起きないよ。

Do not write or read ref.current during rendering, except for initialization. This makes your component’s behavior unpredictable.

during renderingが具体的になんなのか、気になる

hajimismhajimism

Usage

Changing a ref does not trigger a re-render. This means refs are perfect for storing information that doesn’t affect the visual output of your component. For example, if you need to store an interval ID and retrieve it later, you can put it in a ref.

visual outputに関係することをrenderと呼んでいるのかなあ。別のところでは'“Rendering” is React calling your components.'と言っていたから、微妙だなあ。

By using a ref, you ensure that:

  • You can store information between re-renders (unlike regular variables, which reset on every render).
  • Changing it does not trigger a re-render (unlike state variables, which trigger a re-render).
  • The information is local to each copy of your component (unlike the variables outside, which are shared).
  • render間で値が保持されるという意味でふつうのオブジェクトとは異なり、
  • 更新しても再レンダリングされないという意味でstateとは異なり、
  • localであるという意味で、コンポーネントの外に定義される変数とも異なる

参考資料として紹介されていた、Stateとの使い分けの項目。
https://react.dev/learn/referencing-values-with-refs#differences-between-refs-and-state

hajimismhajimism

Pitfall

こういうのを"write or read ref.current during rendering"と言うらしく、非推奨とされている。

function MyComponent() {
  // ...
  // 🚩 Don't write a ref during rendering
  myRef.current = 123;
  // ...
  // 🚩 Don't read a ref during rendering
  return <h1>{myOtherRef.current}</h1>;
}

やるならこう

function MyComponent() {
  // ...
  useEffect(() => {
    // ✅ You can read or write refs in effects
    myRef.current = 123;
  });
  // ...
  function handleClick() {
    // ✅ You can read or write refs in event handlers
    doSomething(myOtherRef.current);
  }
  // ...
}

またはuseStateで値を保持する。

hajimismhajimism

Avoiding recreating the ref contents

  const playerRef = useRef(new VideoPlayer());

initial valueはinitial renderしか使われないのにevery renderで生成されているよっていういつものあれ。

改善案

  const playerRef = useRef(null);
  if (playerRef.current === null) {
    playerRef.current = new VideoPlayer();
  }

Normally, writing or reading ref.current during render is not allowed. However, it’s fine in this case because the result is always the same, and the condition only executes during initialization so it’s fully predictable.

hajimismhajimism

null checkをかわすためのwork around的なものが書いてある。おもろいな。

  function getPlayer() {
    if (playerRef.current !== null) {
      return playerRef.current;
    }
    const player = new VideoPlayer();
    playerRef.current = player;
    return player;
  }
hajimismhajimism

読んでみて

  • useEffectとの接続、useStateとの比較など、他のAPIとの結び付きが強いAPIだなと思った
  • Escape Hatches的なAPIに関しての補助ドキュメントが充実していて、Dan先生流石だなと思った。「王道APIは原理原則さえ守っておけば大体OK」というReact自体の設計がすごいのかも。
このスクラップは2023/07/24にクローズされました