不能在反应中使用 setinterval() 附加数组(状态元素)

Posted

技术标签:

【中文标题】不能在反应中使用 setinterval() 附加数组(状态元素)【英文标题】:cant append array(state element) with setinterval() in react 【发布时间】:2020-08-16 16:30:54 【问题描述】:
 const [timer,setTimer] = useState()
 const [number, setNumber] = useState()
 const [list, setlist] = useState([])

const numberChange = (number)=>
    setNumber(number)
    if (!(list.find(item=>item===number)))
        setlist([...list,number])
  

  const randomNumber=()=> 1+Math.floor(Math.random()*90)

  const randNumberChange=()=>
    let randNumber = randomNumber()
    if (list.find(item=>item===randNumber))
      randNumberChange()
      else
    numberChange(randNumber)
  

  const startTimer = () => 
   setTimer(setInterval(()=>
        randNumberChange()
   , 5000))


const stopTimer=()=>
    clearInterval(timer)

列表总是只呈现一项而不是附加它。

randNumberChange 被单独调用时,列表会被附加,但不会被 setInterval 附加。

startTimer 函数被执行时,以stopTimer 停止,然后再次启动它附加第二个项目然后停止并重复

【问题讨论】:

【参考方案1】:

setlist([...list,number]) 更改为setlist((prevState) => [...prevState, number])。 React 设置状态本质上是异步的。因此,要从状态中获取正确的列表值,您需要从先前状态中获取值。 Doc

建议:可以在useEffect开始间隔,而不是在状态设置定时器。

同样在numberChange 函数中,您应该从之前的状态中获取list,然后在其中附加新的数字。这将确保在添加新号码之前更新 list 值。

import React,  Component, useState  from "react";
import  render  from "react-dom";
import Hello from "./Hello";
import "./style.css";
const Test = () => 
  const [number, setNumber] = useState(null);
  const [list, setlist] = useState([]); 

  const numberChange = number => 
    setNumber(number);
    if (!list.find(item => item === number)) 
      setlist((prevState) => [...prevState, number]);// instead of directly using list value, get it from previous state
    
  ;

  const randomNumber = () => 1 + Math.floor(Math.random() * 90);

  const randNumberChange = () => 
    console.log("here");
    let randNumber = randomNumber();
    if (list.find(item => item === randNumber)) randNumberChange();
    else numberChange(randNumber);
  ;

  const startTimer = () => 
     return setInterval(() =>  randNumberChange(); , 5000);
  

  const stopTimer = (timer) => 
     clearInterval(timer)
  

  React.useEffect(() => 
    const timer = startTimer();
    return ()=> stopTimer(timer);
  , []);

  console.log(list);
  return <div>number</div>;
;

【讨论】:

谢谢你的工作。我直接改变了状态。感谢您的帮助【参考方案2】:

你需要使用useEffect钩子:

useEffect(() => 
  // You don't need timer state, we'll clear this later
  const interval = setInterval(() => 
    randNumberChange()
  ,5000)
  return () =>  // clear up
   clearInterval(interval)
  
,[])

【讨论】:

以上是关于不能在反应中使用 setinterval() 附加数组(状态元素)的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应中使用 setInterval?

在哪里调用 setInterval 反应

反应钩子:新状态值未反映在 setInterval 回调中

卡在反应倒计时应用程序上,想知道如何正确使用 setInterval

当应用程序处于后台时,在反应本机后台计时器 setInterval 中调用 await

反应 setInterval 行为