React Hooks: 如果将一个空数组作为参数传递给useEffect(),它仍然会被调用两次。

608

我正在编写代码,以便在从数据库加载数据之前显示加载消息,然后在加载完成后使用加载的数据渲染组件。为了实现这一点,我同时使用了useState钩子和useEffect钩子。以下是代码:

问题是,当我使用console.log进行检查时,useEffect会触发两次。因此,代码会查询相同的数据两次,这是应该避免的。

以下是我编写的代码:

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;

为什么它被调用了两次,以及如何正确修复代码?

3
你说当你查看控制台日志(console.log),但是没有找到控制台日志。 - Joe Lloyd
3
起初我将它们删除了,因为我已经解释了发生了什么,但根据您的评论,我把它们重新加回来以增加清晰度。 - J.Ko
我的解决方案在 https://stackoverflow.com/a/72676006/2184182,我在这里分享。我猜可以给你帮助。 - Serkan KONAKCI
3
对于使用 React 18 的人 https://dev59.com/OlEG5IYBdhLWcg3wJlLh。翻译:针对React 18用户的问题,链接为https://dev59.com/OlEG5IYBdhLWcg3wJlLh。 - Youssouf Oumar
3
我相信这是因为<React.Strict>发生的。尝试将<React.Strict><Home></React.Strict>替换为只有<Home>。严格模式在本地渲染组件两次,在生产环境中渲染一次。 - Dhanesh Mane
23个回答

0
如上所述,StrictMode是有其目的存在的,仅仅禁用StrictMode并不总是解决问题的正确方法。 useEffect的回调函数最好返回一个清理函数,在下次执行useEffect之前调用该函数。根据发布的问题,我们可以在清理任务中轻松地清除数组,以便该数组不包含重复数据。
 useEffect(()=>{
      // Fill the array here.
      
      // Return a cleanup callback
      return () => {
          // At this point, We can clean the array.
      } 
    
 },[]);

提供一个更具体的编码项目示例,其中我正在调用 setInterval 并注册一些通知。
 useEffect(() => {
    let notificationId = StoreManager.registerForUpdateNotification(() => {
      setStore(StoreManager.getInstance());
    });
    let syncIntervalId = setInterval(() => {
      StoreManager.syncStoreWithCloudInstance();
    }, 1 * 30 * 1000);


    return () => {
      StoreManager.deregisterForUpdateNotification(notificationId);
      clearInterval(syncIntervalId);
    }
  }, []);

希望能有所帮助。


-2
在我的情况下,我只是将useEffect(()=>{ //.... })更改为useEffect(()=>{ //.... },[])

-4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接