React 有关计时器和数组状态的问题

1、useState 为数组

1)反例

定义一个 useState 和生成数据的方法

1
2
3
4
5
6
const [rows, setRows] = React.useState([]);

function createData(column1, column2, column3, column4) {
const column5 = column3 / column4;
return { column1, column2, column3, column4, column5 };
}

按照常规,试图增加元素时,使用以下代码是不生效的:

1
setRows([...rows, createData(column1, column2, column3, column4)]);

如果取 rows 遍历,发现数组只会有最后更新的元素

2)正例

1
setRows((prevRows) => [...prevRows,createData(column1, column2, column3, column4),]);

2、 useEffect 中使用定时器所产生的闭包陷阱

1)反例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const callBack = () => {
……

setRows((prevRows) => [...prevRows, createData(column1, column2, column3, column4)])
}

useEffect(() => {
const intervalId = setInterval({
……
setRows((prevRows) => [...prevRows, createData(column1, column2, column3, column4)])
}, 5000)
console.log('intervalId=' + intervalId)

return () => clearInterval(intervalId)
}, [])

运行后观察控制台,会不断输出计时器 id,说明每次执行间隔就创建一次。有关说明可见文章:making-setinterval-declarative-with-react-hooks

2)正例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const intervalRef = useRef()

const callBack = () => {
……

setRows((prevRows) => [...prevRows, createData(column1, column2, column3, column4)])
}

useEffect(() => {
intervalRef.current = callBack
return () => {}
})

useEffect(() => {
const tick = () => {
intervalRef.current()
}
const intervalId = setInterval(tick, 5000)
console.log('intervalId=' + intervalId)

return () => clearInterval(intervalId)
}, [])