You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中无变化子组件重复渲染的原因及解决方法

问题解析:子组件无props变化却随父组件重渲染的原因与解决办法

先贴一下你的代码方便对照:

import React, { useState, useEffect } from 'react';
const Test = () => {
  const [ count, setCount ] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count up!</button>
      <ChildComponent />
    </div>
  )
}
const ChildComponent = () => {
  useEffect(() => {
    console.log('render!');
    return () => console.log('unmounted...');
  });
  return (
    <div>children</div>
  )
};
export default Test;

为什么点击按钮后ChildComponent会重新渲染?

这是React的默认渲染规则导致的:当父组件的状态或props更新触发自身重渲染时,它所有的子组件(不管有没有接收props、props有没有变化)都会跟着一起重渲染。

在你的代码里,点击按钮后Test组件的count状态更新,触发了Test的重新渲染,作为子组件的ChildComponent自然也会被连带重渲染——哪怕它完全不依赖父组件的任何状态或props。而useEffect在组件重渲染时,会先执行上一次渲染的清理函数(也就是return里的console.log('unmounted...')),再执行新的effect回调(console.log('render!')),所以你会看到控制台输出那两行内容。

怎么避免这种不必要的重新渲染?

最直接的方案是用React.memo包裹子组件,它会对组件的props做浅比较,如果props没有变化,就跳过该组件的重渲染。

修改后的代码如下:

import React, { useState, useEffect, memo } from 'react';
const Test = () => {
  const [ count, setCount ] = useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Count up!</button>
      <ChildComponent />
    </div>
  )
}
// 用memo包裹子组件
const ChildComponent = memo(() => {
  useEffect(() => {
    console.log('render!');
    return () => console.log('unmounted...');
  });
  return (
    <div>children</div>
  )
});
export default Test;

这样修改后,点击“Count up!”按钮时,Test组件依然会正常重渲染,但ChildComponent因为没有props变化,React.memo会阻止它的不必要重渲染,控制台也就不会再输出那两行内容了。

如果之后你的ChildComponent需要接收父组件的props,且props里包含函数、对象这类引用类型的值,那你可能还需要配合useCallback或useMemo来缓存这些引用,确保React.memo的浅比较能正常生效——不过就当前的代码来说,只用React.memo就足够解决问题啦。

内容的提问来源于stack exchange,提问作者Yamada JP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:10:55