以下代码片段演示了在 React 功能组件中使用的 javascript 计时器或间隔的行为与使用类 React 组件时的行为不同。 此外,我还看到了不同的行为。像混乱的执行而不是指示的时间。
是否有解决方法?因为我不喜欢回到 Component 并且不再(或几乎)无法使用 hooks。
https://jsfiddle.net/L5mbqsk9/1/
const App = ()=>{
const [count, setCount] = React.useState(0);
const myfunc = ()=>{
setCount(count+1);
}
React.useEffect(()=>{
const tmr = setInterval(myfunc, 1000);
return () => clearInterval(tmr);
}, [])
return (
<div className="App">
<h1>app</h1>
{count}
</div>
);
}
class App2 extends React.Component
{
constructor(props) {
super(props);
this.state = { count: 0 };
this.tmr = {};
}
myfunc = () => {
this.setState({ count: this.state.count + 1 });
}
tmr;
componentDidMount() {
this.tmr = setInterval(this.myfunc, 1000);
}
componentWillUnmount() {
clearInterval(this.tmr);
}
render() {
return (
<div className="App">
<h1>App2</h1>
{this.state.count}
</div>
);
}
}
ReactDOM.render(
<div>
<div><App /></div>
<div><App2/></div>
</div>,
document.getElementById('container')
);
```
答案 0 :(得分:1)
答案已更新:问题出在您的状态更新程序功能中 我已经用你的小提琴演奏了 10 分钟,发现它工作正常。检查此解决方法
const App = () => {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const myfunc = () => {
setCount(prevCount => prevCount + 1);
}
const tmr = setInterval(myfunc, 1000);
return () => clearInterval(tmr);
}, [])
return (
<div className="App">
<h1>Functional Component</h1>
{count}
</div>
);
}
class App2 extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
this.tmr = {};
}
myfunc = () => {
this.setState((prevState) => {
return {count: prevState.count + 1}
})
}
componentDidMount() {
this.tmr = setInterval(this.myfunc, 1000);
}
componentWillUnmount() {
clearInterval(this.tmr);
}
render() {
return (
<div className="App">
<h1>Class Component</h1>
{this.state.count}
</div>
);
}
}
ReactDOM.render(
<div>
<div><App /></div>
<div><App2/></div>
</div>,
document.getElementById('container')
);
<块引用>
如果新状态是使用先前状态计算的,则使用 setState 的功能更新形式,即 setCount(c => c + 1)
而不是 setCount(count + 1)
。检查https://reactjs.org/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often
答案 1 :(得分:1)
您当前的功能组件仅运行一次效果,因为您已将一个空的依赖数组传递给您的效果挂钩。效果结束 count
的第一个值 0
,并将其设置为 1
。
如果你想要在效果中做的只是纯粹基于前一个状态更新状态,你可以简单地通过传递一个函数而不是一个值到 setCount
来做到这一点:
const App = () => {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
const tmr = setInterval(() => setCount(c => c+1), 1000);
return () => clearInterval(tmr);
}, []);
return (
<div className="App">
<h1>app</h1>
{count}
</div>
);
}
但是,对于更一般的用例,如果您想在效果内部使用间隔/超时,您需要将依赖数组传递给您内部使用的所有值的效果挂钩 - 在这种情况下为 [count]
,因为您通过 myfunc
使用它(间接)。这是一个示例:
const App = () => {
const [count, setCount] = React.useState(0);
const myfunc = () => {
setCount(count+1);
};
React.useEffect(() => {
const tmr = setInterval(myfunc, 1000);
return () => clearInterval(tmr);
}, [count]);
return (
<div className="App">
<h1>app</h1>
{count}
</div>
);
}
请注意,因此,间隔计时器将每秒设置和清除一次,因此您应该可以只使用 setTimeout
代替。如果您不希望效果在每次更新时清除计时器/间隔,您可以考虑使用 ref hooks 存储状态变量并从计时器效果访问 ref
的更详细的方法,而不是国家。