为什么我的控制台打印相同的日期而不是像 html 那样更新

Why is my console printing the same date and not updating like the html

这是我关于 Whosebug 的第一个问题。我目前正在学习反应,我试图制作一个每秒更新一次的实时时钟。我设法通过 useState() 挂钩和 useEffect() 挂钩完成 html 更新。现在,我尝试在控制台更新时将当前时间打印到控制台,但控制台仅显示网站上次刷新的时间。

结果:HTML继续正确更新,但控制台保持在同一时间。

有人可以向我解释我做错了什么或者这个错误的原因是什么吗?

Clock.js:

import { render } from "@testing-library/react";
import React, { useState, useEffect } from 'react';

function Clock() {
    const [dateState, setDateState] = useState(new Date());

    function updateFunc(){
        setDateState(new Date());
        console.log(dateState.toLocaleString('eu-DE', {
            second: 'numeric',
            minute: 'numeric',
            hour: 'numeric',
         }));
        
    }

    useEffect(() => {
           setInterval(() => updateFunc(), 1000);
    }, []);
    return (
        <div className="App">
            <p>
              {' '}
              {dateState.toLocaleDateString('eu-DE', {
                 day: 'numeric',
                 month: 'short',
                 year: 'numeric',
              })}
            </p>
            <p>
             {dateState.toLocaleString('eu-DE', {
                hour: 'numeric',
                minute: 'numeric',
                second: 'numeric',
                hour12: false,
            })}
            </p>
        </div>
    );
}    

  export default Clock;
  

如果我没记错的话,因为 useEffect 没有依赖项,回调永远不会改变。回调有自己的作用域和变量 (dateState),这就是它永远不会改变的原因。

If you pass an empty array ([]), the props and state inside the effect will always have their initial values

source

解决方案是将 updateFunc 添加到 useEffect 依赖项列表。然后你需要用 useCallback 包装 updateFuncdateState 作为依赖项。

注意:当组件订阅无限处理程序(例如 setInterval 或套接字)时,最好使用 cleanup function.

取消订阅
function Clock() {
  const [dateState, setDateState] = useState(new Date());

  const updateFunc = useCallback(() => {
    setDateState(new Date());
    console.log(
      dateState.toLocaleString("eu-DE", {
        second: "numeric",
        minute: "numeric",
        hour: "numeric"
      })
    );
  }, [dateState]);

  useEffect(() => {
    const interval = setInterval(() => updateFunc(), 1000);
    return () => clearInterval(interval);
  }, [updateFunc]);

  return (
    <div className="App">
      <p>
        {" "}
        {dateState.toLocaleDateString("eu-DE", {
          day: "numeric",
          month: "short",
          year: "numeric"
        })}
      </p>
      <p>
        {dateState.toLocaleString("eu-DE", {
          hour: "numeric",
          minute: "numeric",
          second: "numeric",
          hour12: false
        })}
      </p>
    </div>
  );
}

https://codesandbox.io/s/Whosebug-70423606-4umr2