在useEffect中反应丢失变量?

Posted

技术标签:

【中文标题】在useEffect中反应丢失变量?【英文标题】:React losing variable inside of useEffect? 【发布时间】:2021-11-26 01:25:21 【问题描述】:

我正在尝试实现图像幻灯片。 setInterval 在 useEffect 内部使用,以在 x 秒后更改图像。 currentImage 状态保持当前图像,x 秒后它将变为下一个图像,但 react 告诉我每次渲染后索引变量都会丢失。

  const images = [one, two, three, four, five, six, seven];

  const [currentImage, setCurrentImage] = React.useState();

  let index = 0;

  useEffect(() => 
    setInterval(() => 
      if (index < images.length) 
        setCurrentImage(images[index]); 
        index++; 
        console.log(images[index]);
       else 
        index = 0; // If so, reset the index
      
    , 5000);
  , []);


<Grid
      item
      xs=false
      sm=4
      md=7
      sx=
        backgroundImage: `url($currentImage)`,
        backgroundRepeat: "no-repeat",
        backgroundSize: "cover",
        backgroundPosition: "center",
      
    ></Grid>

从 React Hook React.useEffect 内部对 'index' 变量的分配将在每次渲染后丢失。要随着时间的推移保留该值,请将其存储在 useRef Hook 中,并将可变值保留在 '.current' 属性中。否则,你可以直接在 React.useEffect 中移动这个变量

【问题讨论】:

【参考方案1】:

只要用useState改变索引,记得清空定时器。

const images = [one, two, three, four, five, six, seven];
    
      const [currentImage, setCurrentImage] = React.useState();
      const [index,setIndex] = useState(0)
      
      useEffect(() => 
       let timer = setInterval(() => 
          if (index < images.length) 
            setCurrentImage(images[index]); 
            setIndex(prev=>prev+1)
            console.log(images[index]);
           else 
            setIndex(0) // If so, reset the index
          
        , 5000);
          return () => 
            clearTimeout(timer)
          
      , []);
    
    
    <Grid
          item
          xs=false
          sm=4
          md=7
          sx=
            backgroundImage: `url($currentImage)`,
            backgroundRepeat: "no-repeat",
            backgroundSize: "cover",
            backgroundPosition: "center",
          
        ></Grid>

你也可以这样做:

const images = [one, two, three, four, five, six, seven];
    
     
      const [index,setIndex] = useState(0)
      
      useEffect(() => 
       let timer = setInterval(() => 
          if (index < images.length) 
            setIndex(prev=>prev+1)
            console.log(images[index]);
           else 
            setIndex(0) // If so, reset the index
          
        , 5000);
          return () => 
            clearTimeout(timer)
          
      , []);
    
    
    <Grid
          item
          xs=false
          sm=4
          md=7
          sx=
            backgroundImage: `url($images[index])`,
            backgroundRepeat: "no-repeat",
            backgroundSize: "cover",
            backgroundPosition: "center",
          
        ></Grid>

【讨论】:

它不会更改图像,而且它会在 chrome 控制台中输出相同的图像。但是,当我将图像和索引添加为依赖项时,它会更改当前图像,但反应告诉我“'images' 数组使 useEffect Hook 的依赖项(第 96 行)在每次渲染时都发生变化。将其移动到 useEffect 回调中。或者,将 'images' 的初始化包装在它自己的 useMemo() Hook"【参考方案2】:

使用 setTimeout 并在 useEffect 的依赖数组中添加索引。在那个 setTimeout 中,您将更新您的索引。但是不要将索引存储为变量,将其存储在状态中。

【讨论】:

以上是关于在useEffect中反应丢失变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在反应中只运行一次功能

在函数内反应 useEffect 陈旧值

'React Hook内部useEffect中的'dataURI'变量将在每次渲染后丢失

如何取消firebase的useEffect订阅

在此错误消息中“直接在 useEffect 中移动此变量”是啥意思?

React:使用 Refs 修复缺少的依赖警告 useEffect