reactjs 如何在React中的while循环中更新State

k10s72fa  于 2023-05-28  发布在  React
关注(0)|答案(3)|浏览(155)

假设我有这个代码。

var s = [1,2,3,4,5,6,7,8,9,0];
const[arr,setArr]=useState(s);
while(arr.length != 0){
    setArr(arr.splice(0,1));
    console.log(arr); //This returns [2,3,4,5,6,7,8,9,0] and [3,4,5,6,7,8,9,0] and so on until []
}

我在functionanl组件的末尾返回{arr.length}。然而,它首先呈现10,并等待整个while循环运行,然后呈现1。中间的所有数字都被跳过了。
我有点明白为什么会发生这种情况,但无论如何,我可以显示所有的长度吗?我有一个睡眠函数,需要毫秒,并暂停程序的时间,如果它是任何使用,以确保用户可以看到渲染的长度为一个合理的时间。
先谢谢你了!

z31licg0

z31licg01#

假设这是一个功能组件(我猜您指的是useState,而不是const[arr,setArr]=setState(s);中的setState),您需要让组件在设置下一个状态之前呈现每个状态。否则,所有的状态更新都被批处理在一起,并且组件只有在它们全部完成时才再次呈现。
例如:

function Example() {
    const [arr, setArr] = useState([1,2,3,4,5,6,7,8,9,0]);
    // Set up a timer on mount, remove it on dismount and when
    // we run out of values to show
    useEffect(() => {
        const handle = setInterval(() => {
            // Note useing the callback function, so `arr` isn't stale
            // in this callback
            setArr(a => {
                if (a.length) {
                    // Update the array, dropping the first entry
                    return a.slice(1);
                }
                // No more entries, stop the timer
                clearInterval(handle);
                return a;
            });
        }, 500);
        return () => clearInterval(handle);
    }, []);
    return <div>{arr.join()}</div>;
}
nfs0ujit

nfs0ujit2#

我想你可以用useEffect钩子
每次我们改变arr,钩子都会被调用,但会有一些超时

const SHOW_TIMEOUT = 300;
var s = [1,2,3,4,5,6,7,8,9,0];

const [arr, setArr] = useState(s);

useEffect(() => {
  const timeoutId = setTimeout(() => setArr(arr.slice(1)), SHOW_TIMEOUT);

  return () => clearTimeout(timeoutId); // also need to stop timeout in case of unmount
}, [arr]);
eblbsuwk

eblbsuwk3#

就我个人而言,我不喜欢使用useInterval进行任何类型的异步计时黑客攻击。它创建了另一个变量,然后需要调用clearInterval,这只是不可靠的IMO。
setTimeout也不应该是浏览器IMO中异步问题的解决方案。这很容易出错,因为互联网是可变的。如果你的异步函数比你预期的要长一点,你的功能就会中断。
我用递归函数解决了同样的问题。显然,这在useEffect中起作用,useEffect不会批处理,一旦满足条件,就会更新一些useState钩子。您可以使用一个简单的count变量来短路,这样就不会以无限循环结束。

useEffect(() => {
   let count = 0
   function recurseHandleOp() {
      count += 1
      if (count < 100) {
         if (someCondition) {
            setState(true)
         } else {
            recurseHandleOp()
         }
      }
   }
   recurseHandleOp()
}, [])

相关问题