【问题标题】:Infinite Loop when using setState for array对数组使用 setState 时的无限循环
【发布时间】:2021-02-13 03:12:35
【问题描述】:

我想在一个数组中存储 4 个“hi”。而不是:

strArr.push('hi');
strArr.push('hi');
strArr.push('hi');
strArr.push('hi');

我这样做了:

for(let i = 0; i<4; i++){
   setStrArr([...strArr, "hi"])
}

但是,我收到此错误:错误:重新渲染过多。 React 限制渲染次数以防止无限循环

我不知道出了什么问题,我想知道当 i=3 时它是否没有达到。所以我做了一个检查:

for(let i = 0; i<4; i++){
   setStrArr([...strArr, "hi"])
   if(i==3){
      console.log("done")
   }
}

'i'的值确实达到了3,但是为什么我的代码又运行了?

这是我的代码:

function MyApp(){
  const [strArr, setStrArr] = useState([]);
  for(let i = 0; i<4; i++){
       setStrArr([...strArr, "hi"])
       if(i==3){
          console.log("done")
       }
    }      
  return(
    <div>
    </div>
  )
}

【问题讨论】:

  • 你在 JSX 的什么地方做这个 for 循环?你在用钩子吗?钩子的依赖是什么?
  • @Amir-Mousavi 添加了我的代码

标签: arrays reactjs use-state


【解决方案1】:

添加到其他答案,因为您正在执行 同步 代码,我将使用 useLayoutEffect 挂钩。 useLayoutEffect 运行,React 等待它完成。这对于响应等待来说很好,因为代码都是同步的,并且它可以防止您的组件在屏幕上“闪烁”,因为在渲染完成后会调用 useEffect。

function MyApp(){
  const [strArr, setStrArr] = useState([]);

  useLayoutEffect(() => {
     let fourHiArray = [];

    for(let i = 0; i<4; i++){
       fourHiArray = ([...fourHiArray, "hi"])
       if(i==3){
          console.log("done")
       }
    } 

    setStrArr(fourHiArray);
  }, []);
       
  return(
    <div>
    </div>
  )
}

【讨论】:

  • 非常感谢。我之前还没有使用过useLayoutEffect,将阅读它
【解决方案2】:

在重新渲染时调用整个函数 MyApp,因此在每次重新渲染时,您的循环都会重新开始。如果您只想调用一次,请在 useEffect 中调用它。像这样

useEffect(() => {*your code here*}, []}

使用空数组作为第二个参数的 useEffect 仅在第一次渲染时调用。

如果你想设置你的初始状态,我建议你在 useState(['hi','hi','hi','hi'])

【讨论】:

    【解决方案3】:

    我相信您可能会遇到问题,因为调用 setStringArray 是一种“副作用”。

    这将导致函数组件无限重新渲染,因为钩子已经更新了组件的状态,导致重新渲染,然后无限更新状态。

    基本上,您不应该尝试在同一行中同时读取和更新strArray

    您应该只在完全填充数组后调用setStrArr一次

    我认为您还应该考虑使用 useEffect 钩子来实现这样的行为。

    它传递的最后一个参数告诉 React 仅在给定的参数(在本例中为 strArray)发生更改时才运行此 useEffect 挂钩内的代码。

    当您希望在您的组件中具有“副作用”时,此钩子设计。

    所以也许你可以尝试一些类似的方法来防止你的无限重新渲染:

    function MyApp(){
      const [strArr, setStrArr] = useState([]);
    
      useEffect(() => {
         const fourHiArray = [];
    
        for(let i = 0; i<4; i++){
           fourHiArray = ([...fourHiArray, "hi"])
           if(i==3){
              console.log("done")
           }
        } 
    
        setStrArr(fourHiArray);
      }, [strArr]);
           
      return(
        <div>
        </div>
      )
    }
    

    【讨论】:

    • 谢谢。但是你能否进一步解释一下为什么改变状态会导致重新渲染?一直以来,我认为只有使用像 useEffect 这样的钩子才会导致无限地重新渲染。
    • 别担心!希望这可以帮助。因此,当状态更新时,React 组件将总是重新渲染!这是一个“这就是 React 是如何工作的”的案例。这里有一篇很酷的博客文章:lucybain.com/blog/2017/react-js-when-to-rerender/…
    猜你喜欢
    • 1970-01-01
    • 2021-10-29
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    • 2018-05-07
    • 2021-02-13
    • 1970-01-01
    相关资源
    最近更新 更多