reactjs - 是否可以在 React 中创建一个可以在状态中传递的递归函数
问题描述
我正在尝试将存储在状态中的数组中的项目一次渲染到屏幕上。在屏幕上显示一个项目后,它将从数组中删除,然后显示下一个项目,依此类推,直到数组中没有任何项目。让我大吃一惊的是,当函数已经运行时,可以通过 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])
无论如何我可以实现我所追求的吗?
解决方案
您可以使用setTimeout
. 如果队列中有一个项目,则显示它并重新启动超时。下面的示例不是 React 特定的,但它演示了基本思想,包括在事物运行时将项目添加到队列中。
// initial data
const items = [1,2,3,4,5,6];
// get references to dom elements
const appended = document.querySelector('#appended');
const arrayElem = document.querySelector('#array');
const button = document.querySelector('button');
// keep track of the timeout id just so we know
// whether it's currently running.
let timeoutId;
// add an item to the queue when the button is clicked.
button.addEventListener('click', () => {
items.push((items[items.length - 1] || 0) + 1);
arrayElem.innerText = JSON.stringify(items);
// if the timeout isn't already running, start it.
if (!timeoutId) {
update();
}
});
function update (delay = 1000) {
// no items left? clear timeoutId and bail.
if(!items.length) {
timeoutId = null;
return;
}
// get the first item in the queue
const x = items.shift();
// append it to the display
appended.innerHTML += `<div>${x}</div>`;
// update the queue display
arrayElem.innerText = JSON.stringify(items);
// restart the timeout
timeoutId = setTimeout(update, delay);
}
update();
<button>Add Item</button>
<pre id="array"></pre>
<pre id="appended"></pre>
推荐阅读
- sharpziplib - 用于 .NET Core 的 C# SharpZipLib
- javascript - React.js 路由器转到其他页面呈现空白页面
- generics - “预期类型参数,找到整数”从函数调用但不是从 main 调用
- javascript - JSX 元素类型“GoogleMapReact”没有任何构造或调用 signatures.ts(2604)
- javascript - for loop return ,我无法获取值。只返回最后一个值
- sql - 指定要更新的特定年份
- javascript - 在新站点上显示 API 调用结果
- php - 调用 php 中的成员函数 fetch_() 错误
- javascript - 将“错误”设为空,即使 URL 没有返回任何数据
- python - python中的向后消除