Javascript 使用useState在useEffect内设置超时

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 ? {.

我的useState钩子中有一个对象数组,我想更改每个数组元素的一个属性,假设它看起来像:

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限制:)接受所需的答案谢谢!