DB からデータがロードされる前にロード中メッセージを表示し、ロードされた後にロードされたデータでコンポーネントをレンダリングするコードを書いています。これを行うには、useState フックと useEffect フックの両方を使用します。コードは次のとおりです。
問題は、console.log で確認すると、useEffect が 2 回トリガーされることです。コードは同じデータを 2 回クエリしているため、これは避ける必要があります。
以下は私が書いたコードです:
import React from 'react';
import './App.css';
import {useState,useEffect} from 'react';
import Postspreview from '../components/Postspreview'
const indexarray=[]; //The array to which the fetched data will be pushed
function Home() {
const [isLoading,setLoad]=useState(true);
useEffect(()=>{
/*
Query logic to query from DB and push to indexarray
*/
setLoad(false); // To indicate that the loading is complete
})
},[]);
if (isLoading===true){
console.log("Loading");
return <div>This is loading...</div>
}
else {
console.log("Loaded!"); //This is actually logged twice.
return (
<div>
<div className="posts_preview_columns">
{indexarray.map(indexarray=>
<Postspreview
username={indexarray.username}
idThumbnail={indexarray.profile_thumbnail}
nickname={indexarray.nickname}
postThumbnail={indexarray.photolink}
/>
)}
</div>
</div>
);
}
}
export default Home;
なぜ 2 回呼び出されるのか、またコードを適切に修正するにはどうすればよいでしょうか?
ベストアンサー1
useEffect内にconsole.logを配置する
おそらく、コンポーネントの再レンダリングを引き起こす他の副作用がありますが、useEffect 自体は 1 回しか呼び出されません。次のコードでこれを確実に確認できます。
useEffect(()=>{
/*
Query logic
*/
console.log('i fire once');
},[]);
ログ「i fire once」が複数回トリガーされた場合、問題は次の 3 つのいずれかであることを意味します。
このコンポーネントはページ内に複数回表示されます
これは明らかなはずです。コンポーネントはページに数回あり、それぞれがマウントされ、useEffectを実行します。
ツリーの上位にあるものがアンマウントされ、再度マウントされる
コンポーネントは、最初のレンダリング時に強制的にアンマウントおよび再マウントされます。これは、ツリーの上位で発生する「キー」の変更のようなものかもしれません。レンダリングが 1 回だけになるまで、この useEffect を使用して各レベルを上に移動する必要があります。そうすれば、原因または再マウントを見つけることができるはずです。
React.Strictモードがオンになっています
StrictMode は、コードの問題を検出して警告するために、コンポーネントを 2 回レンダリングします (開発時にはレンダリングしますが、本番環境ではレンダリングしません) (これは非常に便利です)。
この回答は@johnhendirxによって指摘され、@rangfuによって書かれました。リンクもしこれがあなたの問題なら、彼に愛を与えてください。このせいで問題が起きているなら、それは通常、useEffectを本来の目的通りに使用していないことを意味します。これについては、ドキュメントに素晴らしい情報があります。ここ