не могу добавить массив (элемент состояния) с setinterval () в реакции - PullRequest
3 голосов
/ 02 мая 2020
 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, а затем запускается снова, добавляет второй элемент, затем останавливается и повторяет

Ответы [ 2 ]

1 голос
/ 02 мая 2020

Измените setlist([...list,number])} на setlist((prevState) => [...prevState, number]). Состояние набора реакции асин c по своей природе. Таким образом, чтобы получить правильное значение списка из состояния, вам нужно получить значение из предыдущего состояния. Do c

Предложение : вместо установки таймера в состояние вы можете запустить интервал в 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>;
};
0 голосов
/ 02 мая 2020

Вам нужно будет использовать useEffect крючок:

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