为了账号安全,请及时绑定邮箱和手机立即绑定

useEffect 内的 setTimeout 和 useState

useEffect 内的 setTimeout 和 useState

杨魅力 2023-08-18 09:54:51
我的 useState 挂钩中有一个对象数组,我想更改每个数组元素的一个属性,假设它看起来像:const array = [{id:1, isDisplayed: false}, {id:2, isDisplayed: false}, {id:3, isDisplayed: true}]虽然我尝试使用setTimeout内部useEffect钩子来更改displayed不需要的任何地方的true属性isDisplayed: true,但它会等待专用时间,并立即更改所有内容,但我想要实现的是用自己的延迟更改每个元素。我的意思是像 const DELAY = 2000setTimeout 之类的东西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);}, [])
查看完整描述

2 回答

?
慕勒3428872

TA贡献1848条经验 获得超6个赞

如果某些项目不可见,您可以设置超时并触发更新。


并跟踪是否显示新项目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'));

这是一个小提琴


查看完整回答
反对 回复 2023-08-18
?
侃侃无极

TA贡献2051条经验 获得超10个赞

const DELAY = 2000;

React.useEffect(() => {

 let count = 1;

 array.forEach((item) => {

   if (!item.displayed) {

     setTimeout(() => {

        item.displayed = true;

        setArray([...array]);

     }, DELAY * count);

     count ++;

   }

 })

}, [])


查看完整回答
反对 回复 2023-08-18
  • 2 回答
  • 0 关注
  • 191 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信