这是这个反应代码中发生的事情吗?
is this what is happening in this react code?
这是一个实验代码,代表对 React 工作原理的可能误解
https://jsfiddle.net/Dr_Coder/h6da2jku/78/
const App = () => {
const {
useState,
useEffect
} = React;
const [firstCount, setFirstCount] = useState(0);
const [secondCount, setSecondCount] = useState(0)
const increment = () => setFirstCount(firstCount + 1)
useEffect(() => {
if(firstCount >= 1) setSecondCount(firstCount)
const timer = setTimeout(() => {
setFirstCount(0)
}, 1000);
return () => clearTimeout(timer)
}, [firstCount, secondCount]);
return (<div className = "app" >
<button onClick={increment}>click {firstCount}</button>
<p>{secondCount}</p>
< /div>
)
}
ReactDOM.render( < App / > , document.getElementById('root'))
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
在我看来,我认为会发生这种情况:
1 - 单击按钮,这将递增 firstCount
2 - 使用 firstCount
的新值渲染
3 - useEffect 将起作用,因为 firstCount
依赖值
发生了变化
4 - 条件为真,这会将 secondCount
的值更改为等于 firstCount
的值
5 - 这将使用 secondCount
的新值再次渲染组件
6 - 计时器结束,并将 firstCount
设置为 0,这将再次渲染组件
7 - 渲染后 useEffect
将起作用,条件为假,什么也没有发生
这就是代码中真正发生的事情吗,react 组件的生命周期是压倒性的,我希望有人澄清代码中到底发生了什么!
是的,大部分是正确的,但是:
您在 #1 之前错过了一点:第一次渲染将调用 useEffect
回调。条件为假,但设置了计时器;除非你在一秒钟内做某事,否则定时器回调会将 firstCount
设置为 0
。
#7 中的 "nothing happens" 不正确 - useEffect
回调仍会启动计时器,一秒钟后,计时器仍会触发。您只是没有注意到,因为它设置的值 firstCount
已经有 (0)。您可以看到,如果您在调试器中单步执行或使用一些 console.log
s:
const {
useState,
useEffect
} = React;
const App = () => {
console.log("App called");
const [firstCount, setFirstCount] = useState(0);
const [secondCount, setSecondCount] = useState(0);
const increment = () => setFirstCount(firstCount + 1);
useEffect(() => {
console.log("useEffect callback");
if (firstCount >= 1) {
console.log("useEffect callback - setSecondCount to " + firstCount);
setSecondCount(firstCount);
}
console.log("useEffect callback - start timer");
const timer = setTimeout(() => {
console.log("timer fired, setFirstCount(0)");
setFirstCount(0)
}, 1000);
return () => {
console.log("useEffect cleanup callback, cancel timer [if it hasn't run]");
clearTimeout(timer);
};
}, [firstCount, secondCount]);
return (
<div className = "app">
<button onClick={increment}>click {firstCount}</button>
<p>{secondCount}</p>
</div>
);
}
ReactDOM.render(<App/> , document.getElementById('root'))
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
您可以在 Dan Abramov 的这篇文章中了解有关 React 组件生命周期的更多信息,特别是关于挂钩的信息。表面上是关于 useEffect
,但实际上它是关于组件生命周期的。
这是一个实验代码,代表对 React 工作原理的可能误解 https://jsfiddle.net/Dr_Coder/h6da2jku/78/
const App = () => {
const {
useState,
useEffect
} = React;
const [firstCount, setFirstCount] = useState(0);
const [secondCount, setSecondCount] = useState(0)
const increment = () => setFirstCount(firstCount + 1)
useEffect(() => {
if(firstCount >= 1) setSecondCount(firstCount)
const timer = setTimeout(() => {
setFirstCount(0)
}, 1000);
return () => clearTimeout(timer)
}, [firstCount, secondCount]);
return (<div className = "app" >
<button onClick={increment}>click {firstCount}</button>
<p>{secondCount}</p>
< /div>
)
}
ReactDOM.render( < App / > , document.getElementById('root'))
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
在我看来,我认为会发生这种情况:
1 - 单击按钮,这将递增 firstCount
2 - 使用 firstCount
3 - useEffect 将起作用,因为 firstCount
依赖值
4 - 条件为真,这会将 secondCount
的值更改为等于 firstCount
5 - 这将使用 secondCount
6 - 计时器结束,并将 firstCount
设置为 0,这将再次渲染组件
7 - 渲染后 useEffect
将起作用,条件为假,什么也没有发生
这就是代码中真正发生的事情吗,react 组件的生命周期是压倒性的,我希望有人澄清代码中到底发生了什么!
是的,大部分是正确的,但是:
您在 #1 之前错过了一点:第一次渲染将调用
useEffect
回调。条件为假,但设置了计时器;除非你在一秒钟内做某事,否则定时器回调会将firstCount
设置为0
。#7 中的 "nothing happens" 不正确 -
useEffect
回调仍会启动计时器,一秒钟后,计时器仍会触发。您只是没有注意到,因为它设置的值firstCount
已经有 (0)。您可以看到,如果您在调试器中单步执行或使用一些console.log
s:
const {
useState,
useEffect
} = React;
const App = () => {
console.log("App called");
const [firstCount, setFirstCount] = useState(0);
const [secondCount, setSecondCount] = useState(0);
const increment = () => setFirstCount(firstCount + 1);
useEffect(() => {
console.log("useEffect callback");
if (firstCount >= 1) {
console.log("useEffect callback - setSecondCount to " + firstCount);
setSecondCount(firstCount);
}
console.log("useEffect callback - start timer");
const timer = setTimeout(() => {
console.log("timer fired, setFirstCount(0)");
setFirstCount(0)
}, 1000);
return () => {
console.log("useEffect cleanup callback, cancel timer [if it hasn't run]");
clearTimeout(timer);
};
}, [firstCount, secondCount]);
return (
<div className = "app">
<button onClick={increment}>click {firstCount}</button>
<p>{secondCount}</p>
</div>
);
}
ReactDOM.render(<App/> , document.getElementById('root'))
<div id="root">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
您可以在 Dan Abramov 的这篇文章中了解有关 React 组件生命周期的更多信息,特别是关于挂钩的信息。表面上是关于 useEffect
,但实际上它是关于组件生命周期的。