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

React函数组件如何基于状态变化控制重渲染、避免子组件不必要渲染

解决方案

问题根因

  • React.memo失效的核心原因是:每次Shop组件重渲染时,addProductHandler都会生成新的函数引用,导致传入Product的props发生变化,memo判定需要重渲染,和Shop的内部状态变更本身没有直接关系。
  • 仅把products作为useMemo依赖时,addProductHandler捕获的是首次渲染的cart闭包,永远指向初始的空数组,因此新增购物车逻辑会异常。

具体实现步骤

1. 用useCallback稳定事件处理函数引用

修改addProductHandler,使用setCart的函数式更新语法,避免依赖外部cart变量,再用useCallback包裹,让函数引用在组件生命周期内保持稳定:

import React, { useState, useCallback } from 'react';
import fakeData from '../../fakeData';
import Product from '../Product/Product';

const Shop = () => {
  console.log('[Shop.js] rendered')
  const first10 = fakeData.slice(0, 10);
  const [products, setProducts] = useState(first10);
  const [cart, setCart] = useState([]);

  // 用useCallback + 函数式更新稳定引用
  const addProductHandler = useCallback((product) => {
    setCart(prevCart => [...prevCart, product]);
  }, []); // 无外部依赖,引用永远不变

  return (
    <div className="shop-container">
      <div className="product-container">
        {products.map(prod => (
          <Product key={prod.id} product={prod} addProductHandler={addProductHandler} />
        ))}
      </div>
      <div className="cart-container">
        <h3>this is cart</h3>
        <h5>Order Summary: {cart.length}</h5>
      </div>
    </div>
  );
};

export default Shop;

2. 给Product组件包裹React.memo

在Product组件的导出位置添加memo包裹,现在传入的product和addProductHandler都是稳定引用,只有product本身发生变化时,Product才会重渲染:

// Product.js 文件
import React, { memo } from 'react';

const Product = ({ product, addProductHandler }) => {
  console.log('[Product.js] rendered', product.id);
  // 组件原有逻辑
  return (
    <div>
      {/* 产品展示逻辑 */}
      <button onClick={() => addProductHandler(product)}>加入购物车</button>
    </div>
  )
}

// 导出时用memo包裹
export default memo(Product);

自定义渲染控制

如果产品对象每次都会生成新的引用(比如接口请求返回新对象),可以给memo传入第二个自定义比较函数,实现和shouldComponentUpdate同等的灵活控制:

export default memo(Product, (prevProps, nextProps) => {
  // 自定义比较逻辑,返回true表示不需要重渲染,返回false表示需要重渲染
  return prevProps.product.id === nextProps.product.id
    && prevProps.product.price === nextProps.product.price
    && prevProps.product.name === nextProps.product.name
    // 其他需要比较的产品属性
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 06:36:04