1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReactのsetStateの誤用によってデータ取得に失敗した話

Last updated at Posted at 2024-11-28

はじめに

同じミスを繰り返してしまったため、今後の参考として記録しておきます。

やろうとしていたこと

Cloud Firestoreからデータを取得し、そのデータをsetPostList関数を使ってpostListに保存し、画面に出力しようとしていました。

最初に書いていたコード

以下は、Cloud Firestoreからデータを取得するために私が書いていたコードです。

const [postList, setPostList] = useState([]);
  useEffect(() => {
    const getPosts = async () => {
      const querySnapshot = await getDocs(collection(db, "posts"));
      querySnapshot.forEach((doc) => {
        setPostList(doc.data());
      });
    }
    getPosts();
  }, []) 

起きたこと

postListが空の配列として出力され、期待した情報を取得できませんでした。

問題の原因

以下のコードが原因でした。

querySnapshot.forEach((doc) => {
  setPostList(doc.data());
});

何が起きていたのか

ReactのsetState(今回の場合はsetPostList)関数は、状態を上書きする動作をします。そのため、ループ内でsetPostListを繰り返し呼び出すと、最後に処理された値だけがpostListに残ることになります。

さらに、setPostListは非同期的に動作するため、タイミングのズレが生じ、意図したデータが保存されないことがあります。

このため、今回は空配列となってしまいデータを正しく取得することができませんでした。

正しい修正方法

以下のように修正することで、正しくデータを保存できます。

①新しい配列を作成する
②setPostListに直接値を代入するのではなく、まとめて更新を行う

useEffect(() => {
  const getPosts = async () => {
    const querySnapshot = await getDocs(collection(db, "posts"));
    const posts = [];
    querySnapshot.forEach((doc) => {
      posts.push(doc.data()); // 配列に追加
    });
    setPostList(posts); // 最後に状態を更新
  };
  getPosts();
}, []);

リファクタリング

forEachの代わりにmapを使うと、新しい配列を返してくれるので、この方法だとよりシンプルに書けるなと思いました。

useEffect(() => {
    const getPosts = async () => {
      const querySnapshot = await getDocs(collection(db, "posts"));
      const posts = querySnapshot.docs.map(doc => doc.data()); // mapを使って配列を作成
      setPostList(posts); // 最後に状態を更新
    };
    getPosts();
  }, []);

まとめ

  • ReactのsetState関数は上書き動作をするため、ループ内で直接呼び出すと正しくデータが保存されない。
  • 配列を使ってデータをまとめて管理することで、状態を一度に更新するようにすることが大切。

参考

今回コードを書くにあたり、こちらの動画を受講しています。
firebaseとReactの連携をわかりやすく教えてくださる素晴らしい動画でした!
ありがとうございました。

また記事執筆にあたり、こちらのリソースを参考にしています。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?