👻
[React] コンポーネント内でデータを扱いたければuseRefで事足りるという事実
コンポーネント内でデータを扱いたければuseRefで事足りるという事実
動作確認はこちら
ソースコード
import { useEffect, useRef, useState } from "react";
const Page = () => {
const [_, dispatch] = useState<{}>();
const that = useRef({ count: 1, text1: "", text2: "" }).current;
useEffect(() => {
const handle = setInterval(() => {
++that.count;
dispatch({});
}, 1000);
return () => clearInterval(handle);
}, []);
return (
<>
<input
value={that.text1}
onChange={(e) => {
that.text1 = e.currentTarget.value;
dispatch({});
}}
/>
<input
value={that.text2}
onChange={(e) => {
that.text2 = e.currentTarget.value;
dispatch({});
}}
/>
<div>count:{that.count}</div>
<div>text1:{that.text1}</div>
<div>text2:{that.text2}</div>
</>
);
};
export default Page;
useStateの大量生産はいらなかった
このプログラム、扱うデータはuseRef
で作成した領域にしか保存していません。useState
は、再レンダリングを発生させるためだけにdispatch
を取り出しています。
useRef
から作成したthat
が、クラスコンポーネントのthis
相当となります。
実はほとんどのプログラムでこの方法が使用できます。変数を書き換えた後に再レンダリングしたければ、dispatch
を呼び出せば良いのです。
useRefにデータを保存する利点
useEffectやuseCallbackでstateの更新タイミングを気にする必要がありません。そこにあるのはリアルタイムなデータです。変数更新のためだけに、第二引数でトリガーになるstateを並べる必要もありません。
useRefにデータを保存する欠点
dispatch
を呼び出す前に書き換えるべき値と元の変数の値が異なっているかどうかの確認を入れないと、内容が変わっていないのに再レンダリングされます。そういう可能性のある場所に判定を一個加える必要があるというのが欠点ですが、大した労力ではありません。
まとめ
うん、なんでもあり
Discussion