P1zza-L1cht
@P1zza-L1cht

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

React firebase 画像が2度読み込まれる

解決したいこと

Reactをフロント、firebaseをバックエンドにしたWebアプリを制作しております。
製作中storageからの画像ファイルをダウンロードして表示したいのですが、2回読み込まれてしまい同じ画像が2回ずつ表示されてしまい
解決方法がわからないです。
エラーコードは出てない状態で、googleのコンソールにもエラーが出ていません。

※個人情報の箇所は隠してます

該当コード

firebase.js
import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";

const firebaseConfig = {
  apiKey:
  authDomain:
  projectId:
  storageBucket:
  messagingSenderId:
  appId: 
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const storage = getStorage(app);
image.js
import React, { useEffect, useState } from "react";
import { storage } from './firebase';
import { ref, listAll, getDownloadURL } from 'firebase/storage';

export default function Image() {
  const [imageList, setImageList] = useState([]);
  const imageListRef = ref(storage, "images/");

  useEffect(() => {
    listAll(imageListRef).then((res) => {
      res.items.forEach((item) => {
        getDownloadURL(item).then((url) => {
          setImageList((prev) => [...prev, url]);
        });
      });
    });
  }, []);

  return(
    <div className="works-container">
      <div className="works-caption"><h2>Works</h2></div>
      <div className="works-contents">
        {imageList.map((url) => {
          return <img src={url} alt="uploaded images" />
      })}
      </div>
    </div>
  );
}

自分で試したこと

useEffectに第2関数を指定した => ループが起こってしまった
mapメソッドをforEachにした => 2度表示が直らなかった

初めてreactのアプリを作成しておりまだまだフックなどについて理解度が追い付いておりませんがご教授お願いします。

0

1Answer

多分StrictModeが原因かと思います。<React.StrictMode>で囲まれたコンポーネントは開発モード時にだけ特定の処理が意図的に二重実行されます。そこは複数回実行される可能性がある場所なので問題が出たなら修正してね、というような事らしいです。

一度しか実行されない事を確実にするには、useRefが利用されるようですね。

import { useRef } from "react";

...省略...

  const doOnce = useRef(false);
  useEffect(() => {
    if(doOnce.current === false) {
      doOnce.current = true;

      //ここに一回のみの処理
      listAll(imageListRef).then((res) => {
        res.items.forEach((item) => {
          getDownloadURL(item).then((url) => {
            setImageList((prev) => [...prev, url]);
          });
        });
      });

    }
  }, []);

参照:

0Like

Comments

  1. @P1zza-L1cht

    Questioner

    返信ありがとうございます。
    StrictModeが引っかかっていたのは盲点でした。
    コード書き換えたところいけました。

Your answer might help someone💌