useEffect 中的 setTimeout 和 useState
setTimeout inside useEffect with useState
我的 useState 挂钩中有一组对象,我想更改每个数组元素中的一个 属性 让我们假设它看起来像:
const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}]
虽然我试图在 useEffect
钩子中使用 setTimeout
来将 属性 displayed
不是 true
的任何地方更改为 isDisplayed: true
,它等待专用时间,并立即更改所有内容,我想要实现的是用自己的延迟更改每个元素。我的意思是像
const DELAY = 2000
和内部 setTimeout 例如 setTimeout(() => ... , DELAY * id)
因为当我渲染 jsx 时,一切都同时出现,我只想在出现每个元素之间做一些小的延迟。例如,第一个元素在 2 秒后出现,第二个在 3 秒后出现(而不是在第一个之后 3 秒)
我当前的代码如下:
React.useEffect(() => {
setTimeout(() => {
setArray(array.map((item)=> !item.isDisplayed ? {...item, displayed: true} : item))
}, DELAY * Math.floor(Math.random() * 5);
}, [])
const DELAY = 2000;
React.useEffect(() => {
let count = 1;
array.forEach((item) => {
if (!item.displayed) {
setTimeout(() => {
item.displayed = true;
setArray([...array]);
}, DELAY * count);
count ++;
}
})
}, [])
如果某些项目不可见,您可以设置超时并触发更新。
并跟踪 revealed
是否显示了新项目,如果没有显示新项目,则停止流程。
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'));
这是一个fiddle
我的 useState 挂钩中有一组对象,我想更改每个数组元素中的一个 属性 让我们假设它看起来像:
const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}]
虽然我试图在 useEffect
钩子中使用 setTimeout
来将 属性 displayed
不是 true
的任何地方更改为 isDisplayed: true
,它等待专用时间,并立即更改所有内容,我想要实现的是用自己的延迟更改每个元素。我的意思是像
const DELAY = 2000
和内部 setTimeout 例如 setTimeout(() => ... , DELAY * id)
因为当我渲染 jsx 时,一切都同时出现,我只想在出现每个元素之间做一些小的延迟。例如,第一个元素在 2 秒后出现,第二个在 3 秒后出现(而不是在第一个之后 3 秒)
我当前的代码如下:
React.useEffect(() => {
setTimeout(() => {
setArray(array.map((item)=> !item.isDisplayed ? {...item, displayed: true} : item))
}, DELAY * Math.floor(Math.random() * 5);
}, [])
const DELAY = 2000;
React.useEffect(() => {
let count = 1;
array.forEach((item) => {
if (!item.displayed) {
setTimeout(() => {
item.displayed = true;
setArray([...array]);
}, DELAY * count);
count ++;
}
})
}, [])
如果某些项目不可见,您可以设置超时并触发更新。
并跟踪 revealed
是否显示了新项目,如果没有显示新项目,则停止流程。
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'));
这是一个fiddle