在计时器回调函数中更改时未修改 React 数组
React array not modified when changed in a timer callback function
以下代码显示项目列表。该列表保存在状态变量 list
中。有两种方法可以将项目添加到列表中:通过单击 Inc 按钮手动添加,或者通过启动计时器每 1 秒将项目添加到列表中。
Inc 按钮有效,但定时器功能无效。检查计时器函数时,状态变量 list
似乎不会在调用之间保持其新长度。
这是为什么?感谢阅读。
import React, { useState } from 'react';
export function Tester() {
const [list, setList] = useState([]);
var timer = null;
function startTimer() {
// Start a timer
if (timer == null)
timer = setTimeout(timeoutCallback, 1000);
}
function timeoutCallback() {
//
timer = null;
//
btnClicked();
//
startTimer();
}
function btnClicked() {
let today = new Date();
let strTime = today.getHours() + ':' + today.getMinutes() + ':' + today.getSeconds();
setList([
...list,
{
name: "item " + strTime,
id: list.length + 1
}
]);
}
const renderedItems = list.map(
X => {
return <span key={X.id}>{X.id}+{X.name} </span>
}
);
return (
<>TESTER
<button onClick={startTimer}>Timer</button>
<button onClick={btnClicked}>Inc</button>
{renderedItems}
</>
);
}
您需要向 setList
提供回调,该回调采用列表的先前状态值并计算新值,因为 list
的值将过时。
setList((prevList) => [
...prevList,
{
name: "item " + strTime,
id: prevList.length + 1
}
]);
另外,当 timer
的当前值发生变化时,您需要使用 useRef
在渲染之间持久化计时器实例而不触发新的重新渲染。
const timer = useRef(null);
function startTimer() {
// Start a timer
if (timer.current == null)
timer.current = setTimeout(timeoutCallback, 1000);
}
function timeoutCallback() {
//
timer.current = null;
//
btnClicked();
//
startTimer();
}
以下代码显示项目列表。该列表保存在状态变量 list
中。有两种方法可以将项目添加到列表中:通过单击 Inc 按钮手动添加,或者通过启动计时器每 1 秒将项目添加到列表中。
Inc 按钮有效,但定时器功能无效。检查计时器函数时,状态变量 list
似乎不会在调用之间保持其新长度。
这是为什么?感谢阅读。
import React, { useState } from 'react';
export function Tester() {
const [list, setList] = useState([]);
var timer = null;
function startTimer() {
// Start a timer
if (timer == null)
timer = setTimeout(timeoutCallback, 1000);
}
function timeoutCallback() {
//
timer = null;
//
btnClicked();
//
startTimer();
}
function btnClicked() {
let today = new Date();
let strTime = today.getHours() + ':' + today.getMinutes() + ':' + today.getSeconds();
setList([
...list,
{
name: "item " + strTime,
id: list.length + 1
}
]);
}
const renderedItems = list.map(
X => {
return <span key={X.id}>{X.id}+{X.name} </span>
}
);
return (
<>TESTER
<button onClick={startTimer}>Timer</button>
<button onClick={btnClicked}>Inc</button>
{renderedItems}
</>
);
}
您需要向 setList
提供回调,该回调采用列表的先前状态值并计算新值,因为 list
的值将过时。
setList((prevList) => [
...prevList,
{
name: "item " + strTime,
id: prevList.length + 1
}
]);
另外,当 timer
的当前值发生变化时,您需要使用 useRef
在渲染之间持久化计时器实例而不触发新的重新渲染。
const timer = useRef(null);
function startTimer() {
// Start a timer
if (timer.current == null)
timer.current = setTimeout(timeoutCallback, 1000);
}
function timeoutCallback() {
//
timer.current = null;
//
btnClicked();
//
startTimer();
}