Javascript 如何在React中增量更新列表?

Javascript 如何在React中增量更新列表?,javascript,reactjs,Javascript,Reactjs,我发表了一篇关于这一点的文章,但没有找到任何解决方案,并且看到了我不理解的行为。我对代码做了一些修改,并将解释一些我尝试过的事情 问题 我想在生成素数时显示它们的列表。首先,这里有一个行为正确的测试函数: const testPrimes=(primes,setPrimes)=>{ 常数t时间=[3,5,7]; for(tptime.entries()的常量[i,p]{ 设置超时(()=>{ 集合素数((旧素数)=> oldPrimes.concat() ); },i*1000); } };

我发表了一篇关于这一点的文章,但没有找到任何解决方案,并且看到了我不理解的行为。我对代码做了一些修改,并将解释一些我尝试过的事情

问题 我想在生成素数时显示它们的列表。首先,这里有一个行为正确的测试函数:

const testPrimes=(primes,setPrimes)=>{
常数t时间=[3,5,7];
for(tptime.entries()的常量[i,p]{
设置超时(()=>{
集合素数((旧素数)=>
oldPrimes.concat()
);
},i*1000);
}
};
这就是所谓的:


导出默认值({args,appState})=>{
常量[primes,setPrimes]=useState([]);
useffect(()=>{
测试素数(setPrimes);
}, []);
返回(
{素数}
);
};
这将以1秒的间隔显示列表中的每个素数,这是所需的行为

在“real”程序中,我使用生成器函数而不是数组:


常量testPrimes3=(参数,setPrimes)=>{
const gen=fPrimes({args});
设i=0;
for(发电机常数p){
控制台日志(“foo”);
设置超时(()=>{
集合素数((旧素数)=>
oldPrimes.concat()
);
}, 100);
}
};
调用
testPrime3
函数类似于上面的
testPrime
(见下文)

调用testPrime3时,我在控制台中看到“foo”显示了3次,每次都有时间间隔,但是当生成器完成时,React中的列表会一次全部填充,而不是对每个prime3递增

我曾尝试在setTimeout中包装对生成器的setEffect调用,但没有效果;以下是已注释掉setTimeout的调用:

  useEffect(() => {
    // setTimeout(() =>
    testPrimes3(args, setPrimes);
    // , 1000);
  }, []);
除了通过setState调用之外,还有更好的方法控制列表中元素的增量呈现吗


更新 建议不要将元素添加到
primes
,而是在组件中呈现它:

const testPrimes3=(args,setPrimes)=>{
const gen=fPrimes({args});
设i=0;
for(发电机常数p){
控制台日志(“foo”);
设置超时(()=>{
集合素数((oldPrimes)=>oldPrimes.concat(p));
}, 100);
}
};
[...]
返回(
{primes.map((p)=>(
))}
);

这没有任何效果。

下面是一个快速片段,演示了
useffect
中的basic,包括返回时清理和传递依赖项数组。它将索引存储为
ref
,该索引用于按原样调整计时,并以增量方式访问
primesArr
的元素。最后,它使用组件返回中的
map()
调用呈现更新的状态

函数应用程序(){
常量[primes,setPrimes]=React.useState([]);
常量primesar=[2,3,5,7,11];
const index=React.useRef(0);
React.useffect(()=>{
设i=index.current;
如果(i
集合素数(prevPrimes=>[…prevPrimes,primesArr[i]]),1000*i;
当前指数=i+1;
return()=>clearTimeout(计时器);
}
},[素数];
返回(
    {primes.map(prime=>
  • {prime}
  • )}
); } ReactDOM.render(,document.getElementById('root'))
我接受了@pilchard的答案,但我改变了他的例子,使之更符合我的意图。我确实修改了我的原始代码,现在它做了我想要的

以下是更改的摘要,并附有注释

import React,{useState,useRef,useffect}来自“React”;
导入“/styles.css”;
/* 
我修改了@pilchard的代码来模拟计算密集型生成器
我的应用程序中有。这不是很好的代码,但我希望使用此方法
循环,而不是使用setTimeout()
*/
函数*genPrime(n){
如果(isNaN(n)| |!isFinite(n)| | n%1 | | n<2)
返回“编号无效:+n;
对于(变量i=2;i1000){
结束=真;
产量一;
}
}当(!结束)
}
}
}
//这里没有零钱
函数isPrime(num){
对于(变量i=2;i{
const nextPrime=primeGen.current.next().value;
//此处无setTimeout调用;延迟内置于生成器中
如果(下一个时间的类型==“编号”){
//常量计时器=设置超时(
// () => 
setPrimes((prevPrimes)=>[…primes,nextPrime])/,
//1000*素数长度
// );
//return()=>clearTimeout(计时器);
}
},[素数];
返回(
    {primes.map((prime)=>(
  • {prime}
  • ))}
); }

正如所料,这以1秒的间隔显示素数。

这是否回答了您的问题?否。如果您查看testPrime,您会看到它以0、1、2秒的间隔调用setPrime,并且列表会以增量方式更新。生成器生成每个素数需要一段时间,然后我在setTimeout()中调用setPrime。这被建议作为渲染器在线程中获取时间的一种方式(我不确定这是否正确,因为渲染发生在不同的线程中)。可能是我无法在JSX组件中完成我想要的操作。无论您是否更改每个调用的计时,我链接的答案都涉及计时(和清理,您不知道)