reactjs - 是否可以在React中制作一个可以在状态中传递的递归函数

标签 reactjs

我正在尝试将存储在状态中的数组中的项目一次渲染到屏幕上。当一个项目显示在屏幕上后,它将从数组中删除,然后显示下一个项目,依此类推,直到数组中没有任何项目为止。让我感到惊讶的是,当函数已经运行时,可以通过 websockets 将项目添加到数组中。所以本质上我想创建一个实时项目队列。当一个或多个项目添加到队列中时,我希望该函数能够触发并在屏幕上逐个显示项目,直到队列为空。

我认为使用最初可以由 useEffect 触发的递归函数可能会起作用。但奇怪的是,在我的 animateDisplay 函数内部,项目的值永远不会改变,但在函数外部,它会像预期的那样发生变化。这就像项目的值被缓存在递归函数中一样。所以我的函数永远重复:

console.log(`outside ${items}`) // If items started as [1,2,3] it would log [1,2,3] then [2,3] then [3] on each render

const animateDisplay = async () => {
    running.current = true
    setDisplay(items[0])
    await timeout(4000)
    setDisplay({})
    setItems(prevState => prevState.slice(1))

    console.log(`inside ${items}`) // If items started as [1,2,3] it would log [1,2,3] on every render

    if (items.length > 0) {
        await timeout(4000)
        await animateDisplay()
    }
    running.current = false
}

useEffect(() => {
    if (running.current === false && items.length > 0) {
        animateDisplay()
    }
}, [items])

我能实现我所追求的目标吗?

最佳答案

主要问题是外壳陈旧。既然你说你基本上是在队列中工作,那么你可以使用 React ref 和间隔计时器来访问队列的前面,并在间隔上使元素出队。

示例:

const [queue, setQueue] = useState([]);

// Ref to store current queue state reference
const queueRef = useRef();

useEffect(() => {
  queueRef.current = queue;
}, [queue]);

// Effect to run the interval and manage the queue
useEffect(() => {
  const timer = setInterval(() => {
    // Access queue front
    const [front] = queueRef.current;

    // Dequeue
    setQueue((queue) => queue.slice(1));
  }, 4000);
  return () => clearInterval(timer);
}, []);

const enqueue = () => {
  setQueue((queue) => queue.concat(/* new value */));
};

Edit is-it-possible-to-make-a-recursive-function-in-react-that-can-be-passed-in-state

更新

更新为仅在填充队列时运行队列。

const [queue, setQueue] = useState([]);

const timerRef = useRef(null);
const queueRef = useRef();

const startQueue = () => {
  // process function
  const tick = () => {
    const [front] = queueRef.current;
    if (!queueRef.current.length) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
    front && console.log(front);
    setQueue((queue) => queue.slice(1));
  };

  // start process
  timerRef.current = setInterval(tick, 1000);

  // immediately invoke
  tick();
};

useEffect(() => {
  // cache reference to queue
  queueRef.current = queue;

  // if queue populated and not running, start queue
  if (queue.length && !timerRef.current) {
    startQueue();
  }
}, [queue]);

useEffect(() => {
  // clear any running timers when unmounting
  return () => clearInterval(timerRef.current);
}, []);

const enqueue = () => {
  setQueue((queue) => queue.concat(count++));
};

Edit is-it-possible-to-make-a-recursive-function-in-react-that-can-be-passed-in-state (forked)

关于reactjs - 是否可以在React中制作一个可以在状态中传递的递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69279362/

相关文章:

reactjs - 如何更新按钮标题?

javascript - Redux - 如何从商店获取数据并发布它

reactjs - React Router 深度链接

javascript - 无法读取未定义的 React Hooks 的属性

javascript - 是否有 strip 结帐成功案例的回调函数?

javascript - 在 React Native 中将新的键/值添加到对象中

javascript - 我们如何模拟 Redux 异步操作的获取?

reactjs - 将完整的 React Web 应用程序移植到 React Native

javascript - 如何在 React 的构造函数中处理 Null Props

reactjs - 如何切换 reducer 中的属性?