🧸

やっぱりhooksでコンポーネントは返さない?

2022/04/17に公開
後日談 (2022年05月05日)

でも usePortal みたいに変数名をPascalCaseにして useCallback して使えばいいのかも。

https://www.npmjs.com/package/react-useportal

import usePortal from 'react-useportal'

const App = () => {
  const { Portal } = usePortal()

  return (
    <Portal>
      This text is portaled at the end of document.body!
    </Portal>
  )
}

※使用方法を引用

上記を参考にすると、チェックボックスは以下のように書けそう。

const labels = ['check 1', 'check 2', 'check 3']

const App: React.FunctionComponent = () => {
  // const [isAllChecked, renderChecks] = useChecks(labels)
  const { isAllChecked, Checks } = useChecks(labels)

  return (
    <div>
      {/* {renderChecks} */}
      <Checkes />
      <p>
        <button disabled={!isAllChecked}>次へ</button>
      </p>
    </div>
  )
}

また検証してみます。


コンポーネントを描画するとき、そのコンポーネントに依存するstateが多い場合、色々なstateを親に持たせておくのが大変だと思っていたところ、

https://engineering.linecorp.com/ja/blog/line-securities-frontend-3/

の記事が大変役に立ちました。
hooksでコンポーネント返していいのか!」と。

const labels = ['check 1', 'check 2', 'check 3']

const App: React.FunctionComponent = () => {
  const [isAllChecked, renderChecks] = useChecks(labels)

  return (
    <div>
      {renderChecks}
      <p>
        <button disabled={!isAllChecked}>次へ</button>
      </p>
    </div>
  )
}

※記事の最後のまとめ部分、一部を修正して引用

実際うまく動いたし、依存関係も整理され、見通しもとてもよくなりました。

でも、このやり方で組み上げていくと {renderChecks} の部分が(コンポーネントが描画されることがわかりずらいな…)と感じるようになり、やっぱりコンポーネントは <Checks /> みたいに書きたくなりました。

依存関係の解決に困ったときは、コンポーネントに渡すpropsが適切か、もう一度考えてみるのがよさそうでした。

const labels = ['check 1', 'check 2', 'check 3']

const App: React.FunctionComponent = () => {
  const [isAllChecked, setIsAllChecked] = useState(false)

  return (
    <div>
      <Checks labels={labels} setIsAllChecked={setIsAllChecked} />
      <p>
        <button disabled={!isAllChecked}>次へ</button>
      </p>
    </div>
  )
}

React のコンポーネントに props として渡せるものに制限はありません。
via: コンポジション vs 継承 – React

Discussion

ログインするとコメントできます