这是这个反应代码中发生的事情吗?

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.logs:

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,但实际上它是关于组件生命周期的。