首页 > 解决方案 > 反应功能组件重新渲染一次,即使状态的值没有改变

问题描述

我是 React 功能组件的新粉丝。当我阅读文档并尝试做一些实验时,我发现了一个值得怀疑的案例。

我有一个自定义钩子“ useAutoIncrement ”,它有一个setInterval,它每秒增加一个“num”。当此时间间隔触发时,主要组件会重新渲染。然后我将 setState 更改为 custom-hook 0的固定数字。正如预期的那样,主要组件不会重新渲染。到目前为止我们一直很好:)

然后尝试单击主组件中事件处理程序的“按钮”增量,主组件重新渲染,自定义挂钩也重新渲染。但是当间隔在第一次运行到 setState 值0时,奇怪的事情发生了。主要组件和自定义挂钩似乎重新渲染(我放置了一些 consolg.log 并显示出来),但在主组件和自定义挂钩的useEffect中都没有显示 console.log。

在此处输入图像描述

看看这张图片,3 条蓝线。第一条蓝线在钩子效应区间函数内。它使用未更改的值调用setNum 。主要组件不应该重新渲染,但似乎确实如此。第二和第三蓝线打印出来,他们重新渲染

谁能给我解释一下这个案子? 这是我的代码:https ://codesandbox.io/s/react-playground-ddqzc?file=/index.js

import React, { useState, useEffect } from 'react';
 
const useAutoIncrement = () => {
  const [num, setNum] = useState(0)

  useEffect(() => {
    console.log("useAutoIncrement useEffect")
    const interval = setInterval(() => {
      console.log("useAutoIncrement useEffect interval")
      setNum((currentNum) => {
        return 0 // return fixed number
      })
    }, 5000)

    return () => {
      console.log("useAutoIncrement useEffect return")
      clearInterval(interval)
    }
  });

  console.log("render useAutoIncrement")
  return 0
}

const CustomHook = () => {
  const initialCount = {value: 5};
  const [count, setCount] = useState(initialCount);

  const num = useAutoIncrement()
 
  const handleIncrement = () => {
    setCount((currentCount) => {
      return Object.assign({}, currentCount, {value: 2})
    });

    console.log("handleIncrement")
  }


  useEffect(() => {
    console.log("CustomHook useEffect")
    
    return () => {
      console.log("CustomHook useEffect return")
    }
  })

  console.log("CustomHook render")
 
  return (
    <div>
      <h1>{count.value}</h1>
 
      <button type="button" onClick={handleIncrement}>
        Increment
      </button>

      <p>Auto Increase Number: {num}</p>
    </div>
  );
};
 
export default CustomHook;

标签: reactjsreact-functional-component

解决方案


当您单击按钮并触发状态更改时,您的组件已更新并重新渲染 - 您可以从上面的日志中看到这一点。

  • render useAutoIncrement
    • 这是函数触发时组件遇到的第一条控制台消息
  • CustomHook render
    • 这是 JS 堆栈中的下一个调用
  • useAutoIncrement useEffect return
    • 因为您正在重新渲染,所以前一个正在卸载,导致它运行,但 react 以特定顺序执行此操作,因此您在新调用useAutoIncrement的 useEffect 将运行之前看到它
  • CustomHook useEffect return
    • 在下一个 useEffect 中也会发生同样的事情
  • useAutoIncrement useEffect
    • 反应现在运行 useEffect 现在前一个已清理
  • CustomHook useEffect
    • 还有这个
  • useAutoIncrement useEffect interval
    • 间隔准时发生
  • render useAutoIncrement
    • 如前所述,setState 强制更新
  • CustomHook render
    • 因为 useAutoIncrement 再次运行,num也更新了,即使它是相同的数字

希望这会有所帮助


推荐阅读