Javascript 使用useState在useEffect内设置超时
我的useState钩子中有一个对象数组,我想更改每个数组元素的一个属性,假设它看起来像:Javascript 使用useState在useEffect内设置超时,javascript,reactjs,react-hooks,settimeout,Javascript,Reactjs,React Hooks,Settimeout,我的useState钩子中有一个对象数组,我想更改每个数组元素的一个属性,假设它看起来像: const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}] React.useEffect(() => { setTimeout(() => { setArray(array.map((item)=> !item.isDisplayed ? {.
const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}]
React.useEffect(() => {
setTimeout(() => {
setArray(array.map((item)=> !item.isDisplayed ? {...item, displayed: true} : item))
}, DELAY * Math.floor(Math.random() * 5);
}, [])
当我试图在setTimeout
内部useffect
钩子中使用setTimeout
来更改属性显示的true
到isDisplayed:true
时,它会等待指定的时间,并立即更改所有内容,我想要实现的是以自己的延迟更改每个元素。我是说
const DELAY=2000
和内部setTimeout,例如setTimeout(()=>…,DELAY*id)
因为在渲染jsx时,所有内容都会同时显示,我只想在显示每个元素之间做一些小的延迟。例如,第一个元素出现在2s之后,第二个元素出现在3s之后(而不是第一个元素出现在3s之后)
我当前的代码如下所示:
const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}]
React.useEffect(() => {
setTimeout(() => {
setArray(array.map((item)=> !item.isDisplayed ? {...item, displayed: true} : item))
}, DELAY * Math.floor(Math.random() * 5);
}, [])
如果某些项目不可见,可以设置超时并触发更新
并跟踪新项目是否显示为discovered
,如果未显示新项目,则停止流程
function TodoApp() {
const [items, setItems] = React.useState([
{ id: 1, isDisplayed: false },
{ id: 2, isDisplayed: false },
{ id: 3, isDisplayed: false },
]);
React.useEffect(() => {
let currentTimeout = null;
const displayMoreItems = () => {
setItems(prevItems => {
let revealed = false;
const nextItems = prevItems.map(item => {
if (!revealed && !item.isDisplayed) {
revealed = true;
return { ...item, isDisplayed: true };
}
return item;
});
if (revealed) {
currentTimeout = setTimeout(() => {
displayMoreItems();
}, 1000);
}
return nextItems;
});
};
currentTimeout = setTimeout(() => {
displayMoreItems();
}, 1000);
return () => {
if (currentTimeout) {
clearTimeout(currentTimeout);
}
};
}, [setItems]);
return <div>{items.map(item => (item.isDisplayed ? item.id : null))}</div>;
}
ReactDOM.render(<TodoApp />, document.querySelector('#app'));
函数TodoApp(){
const[items,setItems]=React.useState([
{id:1,isDisplayed:false},
{id:2,isDisplayed:false},
{id:3,isDisplayed:false},
]);
React.useffect(()=>{
让currentTimeout=null;
const displayMoreItems=()=>{
setItems(PreviItems=>{
让它暴露=虚假;
const nextItems=previitems.map(item=>{
如果(!display&&!item.isDisplayed){
揭露=真实;
返回{…项,isDisplayed:true};
}
退货项目;
});
如果(透露){
currentTimeout=setTimeout(()=>{
displayMoreItems();
}, 1000);
}
返回nextItems;
});
};
currentTimeout=setTimeout(()=>{
displayMoreItems();
}, 1000);
return()=>{
如果(当前超时){
clearTimeout(currentTimeout);
}
};
},[setItems]);
返回{items.map(item=>(item.isDisplayed?item.id:null));
}
ReactDOM.render(,document.querySelector('#app');
这是一个这将使项目发生变异,不会导致重新加载,实际上它不会触发重新加载,这是这里的主要目标。我建议取消返回值中的任何超时,作为useffects的函数。是的,这是真的,但因为这只是一个模拟,你有
如果(显示){…}
我的eslint说“不必要的条件,价值总是虚假的。eslint@typescript-eslint/无不必要的条件“
relevated的声明必须移到setItems
上方的一行,闭包可以。它不amtter.nvm当我移动这条线时,它运行良好,这一切取决于您的eslint限制:)接受所需的答案谢谢!