我在尝试使用setInterval
更改反应中的状态时遇到问题。 为什么函数"alert"总是显示"null"消息?
import React, { useEffect, useState } from 'react';
const Playlist = (props) => {
const [test, setTest] = useState("");
useEffect(() => {
setInterval(load, 3000)
}, []);
const load = async () => {
alert(test)
setTest("TEST");
}
return (
<div>
{test}
</div>
)
}
export default Playlist
问题 :
是传递到setInterval
闭包中的回调,它在第一次渲染中访问test
变量。
溶液:
您可以在状态发生任何变化时立即clearInterval
和setInterval
const { useState , useEffect , useCallback } = React;
const App = () => {
const [test, setTest] = useState("");
useEffect(() => {
const intrvl = setInterval(load, 3000);
return () => clearInterval(intrvl);
}, [test]);
const load = () => {
alert(test)
setTest("TEST");
}
return (
<div>
{test}
</div>
)
}
ReactDOM.render(<App />, document.getElementById('react-root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react-root"></div>
问题是useEffect
从第一个渲染中捕获等于空字符串的test
。我们永远不会重新应用效果,因此 setInterval 中的闭包始终引用第一次渲染中的测试。
注意:setInterval
不会及时描述流程 - 一旦设置了间隔,除了清除它之外,您无法更改任何有关它的内容。
当我们将一个空的依赖项[]
数组传递给 useEffect 时,它只在挂载时运行 useEffect,在卸载组件时运行清理。
一种方法是将test
添加到依赖项数组中,以便每当测试更新时,都会调用 useEffect。
useEffect(() => {
const intervalId = setInterval(load, 3000);
return () => clearInterval(intervalId);
}, [test]);
但是由于我们在useEffect中使用了test
,我们可以删除空的[]
依赖项数组,因此每次我们设置状态(组件被重新渲染(时都会调用useEffect,并且将通过访问最新的测试状态来创建新的setInterval,如下所示
useEffect(() => {
const intervalId = setInterval(load, 3000);
return () => clearInterval(intervalId);
});
另一种可能的方法是更新区间闭包中的状态,例如
useEffect(() => {
const id = setInterval(() => {
setTest("TEST");
}, 3000);
return () => clearInterval(id);
});
const App = () => {
const [test, setTest] = useState("");
useEffect(() => {
const intervalId = setInterval(load, 3000);
return () => clearInterval(intervalId);
});
const load = () => {
alert(test)
setTest("TEST");
}
return (
<div>
{test}
</div>
)
}
设置计数的间隔示例,以便您可以看到状态更改