React コードで最も一般的な問題


React を使い始めたのは約 5 年前です.私が React コードで見た最も一般的な問題は、状態の重複です.

重複した状態は常に問題を引き起こします.

では、重複状態とはどういう意味ですか?

ブログ投稿を表示するコンポーネントがあるとしましょう:

function Blogposts({ blogposts }) {
  return <ul>{blogposts.map(blogpost => ...)}</ul>
}


このブログ投稿のリストに検索を追加する場合:

function Blogposts({ blogposts }) {
  const [filtered, setFiltered] = useState(blogposts)
  const [search, setSearch] = useState("")

  return (
    <div>
      <input
        type="text"
        onChange={e => {
          setSearch(e.target.value)
          setFiltered(
            blogposts.filter(
              blogpost => e.target.value === "" || blogpost.title.includes(e.target.value))
            )
          )
        }}
        value={search}
        placeholder="Search"
      />
      <ul>{filtered.map(blogpost => ...)}</ul>
    </div>
  )
}


注: 検索が空の場合、すべてのブログ投稿を表示したい ( e.target.value === "" )

これは機能しますが、このアプローチにはいくつかの欠点があります.
  • blogposts が変更された場合、filtered リストが更新されていることを確認する必要があります
  • ページ間で search パラメータを保持する場合 (クエリ パラメータを使用するなど)、filtered リストが正しく初期化されていることを確認する必要があります
  • コンポーネントは
  • について推論するのが難しい
    filtered が常に最新であることを確認する必要があります.

    これは、コンポーネントが大きいほど難しくなります.

    どうすればこれを修正できますか?

    この場合、 filteredblogposts がある場合、 search リストを計算できます.

    function Blogposts({ blogposts }) {
      const [search, setSearch] = useState("")
    
      return (
        <div>
          <input
            type="text"
            onChange={e => setSearch(e.target.value)}
            value={search}
            placeholder="Search"
          />
          <ul>
           {blogposts
             .filter(
               blogpost => search === "" || blogpost.title.includes(search)
             )
             .map(blogpost => ...)
           }
          </ul>
        </div>
      )
    }
    


    コンポーネントのレンダリング サイクルの一部として、フィルタリングされたリストを計算します.

    状態が変わるたびに、コンポーネントは再レンダリングされます.

    これは、filtered を最新の状態に保つ必要がなくなったことを意味します.
  • 私たちは考えることから心を解放します filtered
  • フィルタリングされたリストは常に正しい
  • コンポーネントは
  • について推論する方が簡単です

    そこで、私の個人的なルールは次のとおりです.

    可能であれば、常に状態から派生します.

    パフォーマンスはどうですか?

    ほとんどの場合、JavaScript は高速なので (重いものを計算している場合を除いて) 無視できます.

    必要に応じて useMemo も使用できます.

    このブログ投稿が役に立ったかどうか教えてください. 😊