首页 > 解决方案 > 循环遍历数组并一次显示单个项目,动态持续时间,如 react js 中的 setTimeout 或 SetInterval

问题描述

我有一个 Media.json 文件,它有 6 个媒体对象(名称、持续时间、文件类型)。我想遍历它们,并希望根据媒体对象持续时间属性一次显示一个具有动态持续时间的项目。我已经尝试使用 setTimeout 和 SetInterval 在它们内外循环,但仍然无法做到这一点。我正在使用带有功能组件的 react js。帮助将不胜感激。我的示例代码。

const [mediaItem, setMediaItem] = useState({})
const items = [{ name: 'one' }, { name: 'two' }, { name: 'three' }];
const renderMedia = () => {
for (let i = 0; i < items.length; i++) {
  setTimeout(() => {
    setMediaItem(items[i]);
    console.log(mediaItem);
  }, 5000);
}
// return items[currentIndex].name;

};

谢谢

标签: arraysreactjsloopsstatesetinterval

解决方案


问题

  1. for 循环是完全同步的代码。在循环中更新反应状态时,您必须使用功能状态更新,否则每个后续排队更新都会覆盖先前的更新。
  2. for 循环位于组件主体中,这意味着每次组件由于状态更新而重新渲染时,都会设置另一组入队状态更新。

解决方案

如果您想在同步循环中将所有更新排队,那么应该在挂载useEffect钩子中完成一次,并对超时应用增量,这样它们就不会同时过期。

useEffect(() => {
  items.forEach((item, i) => setTimeout(
    () => setMediaItem(item),
    (i + 1) * 5000, // 5000, 10000, 15000
  ));
}, []);

在状态中使用/存储数组index并在间隔内增加它可能会更容易一些。

const items = [{ name: "one" }, { name: "two" }, { name: "three" }];

function AppExample() {
  const [mediaItem, setMediaItem] = React.useState(items[0]); // <-- seed initial state
  const [index, setIndex] = React.useState(0);

  React.useEffect(() => {
    const timerId = setInterval(
      () => setIndex((i) => (i + 1) % items.length), // <-- increment index
      2000
    );
    return () => clearInterval(timerId);
  }, []);

  React.useEffect(() => {
    setMediaItem(items[index]); // <-- update media state when index updates
  }, [index]);

  return (
    <div className="App">
      <div>Media: {mediaItem.name}</div>
    </div>
  );
}

使用动态时间持续时间编辑循环遍历数组和显示单个项目


推荐阅读