【问题标题】:setInterval inside useEffect hooksetInterval 在 useEffect 挂钩内
【发布时间】:2022-01-06 04:28:25
【问题描述】:

首先,我会说我对反应很陌生。

我正在从 firebase 获取数据并随机更改屏幕上 setInterval 中的数据。发生了一些我不明白的事情,所以我想问一下。

  1. 对区间和useEffect的工作原理有疑问。在 useEffect 内部没有依赖关系,因此 useEffect 仅在第一次执行。当useEffect 只工作一次时,间隔内的函数如何在每隔几秒后工作?我认为区间函数在useEffect,useEffect 内部应该执行才能运行区间函数。

  2. 当我在 setInterval 中将时间设置为 1000 时,反应说current_quote 状态未定义,但是当我将其设置为 2000 或更大时一切都很好。为什么?

  3. 返回 useEffect 的回调函数。我知道它每次都会在下一次渲染之前运行,以清除上一次渲染的间隔,但是当我在内部控制台返回时,为什么它不执行?

import  db from '../components/db'
import {useState,useEffect} from 'react'
const Home = ()=>{
    const [current_quote,set_current_quote] =  useState({});
    const [isloaded, set_loaded]= useState(false)
    let arr_data=[];

    useEffect(()=>{
      // fetching data from database
        db.collection("data").get().then((querySnapshot) => {
         querySnapshot.forEach(element => {
         var data = element.data();
         arr_data.push(data);      
         })
        })
           const interval =  setInterval(()=>{ // randomly changing state
            set_current_quote(arr_data[Math.floor(Math.random()*(arr_data.length))])
            set_loaded(true);         
        },1000)

        return ()=>{
            clearInterval(interval)
        }   
    },[])

   return (   
    <div>
        <h1>{ isloaded  &&  current_quote.Quote} </h1> // displaying random data
        <h4>{ isloaded  &&  current_quote.Author}</h4>
     </div>        
    )}
    export default Home;

【问题讨论】:

  • 这是一个问答网站。请注意,question 是单数,而不是复数。它不是一个编号的问题列表网站。如果您有多个问题,则需要创建单独的帖子来提问。

标签: reactjs


【解决方案1】:

希望这能推动您的理解:

  1. useEffect 运行一次,从数据库读取一次,并设置一次间隔函数。 javascript引擎将调用您设置的间隔函数,直到您clearInterval()它。代码没问题。在间隔方法中,您正在调用从 React 的 useState() 钩子接收到的方法 set_current_quote()。这会弄脏组件并导致它重新渲染。

  2. 您的代码第一次运行时,current_quote = {},因此 current_quote.Quote 未定义。但是,虽然 current_quote 未定义,但 isloaded 应该是错误的 - 所以乍一看我不确定您为什么会收到未定义的错误。

  3. 组件被拆除时调用useEffect返回回调。如果您从 dom 中删除组件(例如通过导航离开),您会看到它被调用。

您可以将 arr_data 移动到 useEffect 内部。它不会在该范围之外使用,也不会跨渲染保存(没有 const [arr, setArr] = useState())。

// instead of this...
let arr_data = []
querySnapshot.forEach(element => {
  var data = element.data();
  arr_data.push(data);      
})

// you can do this...
let arr_data = querySnapshot.map(element => element.data())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-13
    • 2021-05-24
    • 2021-06-16
    • 2020-04-07
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多