useRefのdocsを読む
これです
useRef is a React Hook that lets you reference a value that’s not needed for rendering.
”that’s not needed for rendering”がなんなのか
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が具体的になんなのか、気になる
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との使い分けの項目。
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で値を保持する。
Manipulating the DOM with a ref
React will set the current property back to null when the node is removed from the screen.
地味に意識したこと無かったな。
詳細はここに書いてあるらしい
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.
null checkをかわすためのwork around的なものが書いてある。おもろいな。
function getPlayer() {
if (playerRef.current !== null) {
return playerRef.current;
}
const player = new VideoPlayer();
playerRef.current = player;
return player;
}
refのforwordingもありますよねそういえば。
読んでみて
- useEffectとの接続、useStateとの比較など、他のAPIとの結び付きが強いAPIだなと思った
- Escape Hatches的なAPIに関しての補助ドキュメントが充実していて、Dan先生流石だなと思った。「王道APIは原理原則さえ守っておけば大体OK」というReact自体の設計がすごいのかも。