React.useStateは2種類ある

React.useStateにはある点で2種類あると考えている。 UI制御専用のもの そうでないもの これはUIコンポーネントに含められるかどうか、の違いがある。 UIコンポーネント UI制御専用のものとは。 テキストをマスクしたりしなかったりするコンポーネントを考える。(type=“password"は便宜上使用。) const [mask, setMask] = React.useState(false); return ( <> <input type={view ? "text" : "password"} /> <span onClick={() => setMask(!v => v)}>toggle</span> </> ) 入力された文字を表示するかどうかを、UIの責務の範囲内で完結されるべきと言えるときは、React.useStateが使って実装するのが良い(かもしれない)。 言い換えれば、UIコンポーネントとして表示/非表示を制御すると決めた場合、React.useStateを使っても問題はない。 強めに言えば、大体のUIコンポーネント内のReact.useStateは、表示/非表示を制御するのみと言っても良い。逆に言えば、それ以外のReact.useStateは、UIコンポーネントに含めるべきではないと考え始めると良いかもしれない。 UIコンポーネント外 先の例で言えば、input.valueに何を入力しているかは、UIコンポーネントの責務範囲外で、外部から受け入れるべき。 type Props = Pick<React.ComponentProps<"input">, "value">; function MaskedTextInput(props: Props) { } 便利なUIコンポーネントを作ろうとしてか、ビジネスロジックや他APIとの通信までコンポーネントに含まれてしまうパターンはよくありがちか。 設計方針次第ではあるが、ピュアなUIコンポーネントを作ろうと思ったときには、参考になるかもしれない。 例 いくつか例がある方がわかりやすいかもしれない。 React.useStateよりもコンポーネントの責務や命名のほうが主題かもしれない。 クリップボードにコピーするコンポーネント クリップボードに表示する値が動的に変化する場合は、それはおそらく呼び出し元で定義され流し込まれるべきかもしれない。 ここで利用したReact.useStateは、コピーしたらチェックマークを表示するようにするために利用されている。 function CopyInput(inputProps: React.ComponentProps<"input">) { const [copied, setCopied] = useState(false); const buttonProps = { onClick: () => { navigator. [続きを読む]