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

React:浏览器窗口Resize时避免子组件重渲染的问题

解决方案:避免Resize时React子组件不必要重渲染

核心问题分析

你之前的useMemo未生效的原因有两点:

  1. 未用React.memo包裹子组件,即使元素引用不变,子组件仍会随父组件重渲染
  2. 未缓存整个columns数组,且在不同布局分支中重复创建子组件元素,导致元素引用每次都变化

步骤1:用React.memo包裹目标子组件

给PaymentOption(以及其他需要优化的子组件)添加React.memo,让它仅在props变化时重渲染:

// PaymentOption组件定义文件
import React from 'react';

const PaymentOption = React.memo((props) => {
  // 组件原有逻辑
});

export default PaymentOption;

步骤2:缓存子组件元素与columns数组

在父组件中,分别缓存每个子组件的元素实例,再缓存整个columns数组,确保仅当布局状态或子组件props变化时才更新:

const Parent = (props) => {
  // 1. 缓存单个子组件元素,依赖对应props
  const cachedCustomerInfo = useMemo(() => (
    <CustomerInfo {...customerProps} />
  ), [customerProps]);

  const cachedContactInfo = useMemo(() => (
    <ContactInformation {...contactProps} />
  ), [contactProps]);

  const cachedPaymentOption = useMemo(() => (
    <PaymentOption {...paymentProps} />
  ), [paymentProps]);

  const cachedAddressInfo = useMemo(() => (
    <AddressInfo {...addressProps} />
  ), [addressProps]);

  // 2. 缓存columns数组,依赖布局状态和缓存的子组件元素
  const columns = useMemo(() => {
    if (isOneColumnLayout) {
      return [
        <Fragment key="single-col">
          {cachedCustomerInfo}
          {cachedContactInfo}
          {cachedPaymentOption}
          {cachedAddressInfo}
        </Fragment>
      ];
    } else if (isTwoColumnLayout) {
      return [
        <Fragment key="left-col">
          {cachedCustomerInfo}
          {cachedContactInfo}
          {cachedPaymentOption}
        </Fragment>,
        <Fragment key="right-col">
          {cachedAddressInfo}
        </Fragment>
      ];
    }
    // 默认三栏布局
    return [
      <Fragment key="col-1">
        {cachedCustomerInfo}
      </Fragment>,
      <Fragment key="col-2">
        {cachedContactInfo}
        {cachedPaymentOption}
      </Fragment>,
      <Fragment key="col-3">
        {cachedAddressInfo}
      </Fragment>
    ];
  }, [isOneColumnLayout, isTwoColumnLayout, cachedCustomerInfo, cachedContactInfo, cachedPaymentOption, cachedAddressInfo]);

  return (
    <Fragment>
      <FlexColumns columns={columns} />
    </Fragment>
  );
};

步骤3:优化Resize事件监听(可选)

给resize事件添加防抖,减少父组件因窗口频繁调整而触发的重渲染次数:

const Parent = (props) => {
  const [windowWidth, setWindowWidth] = useState(window.innerWidth);

  useEffect(() => {
    // 防抖函数:200ms内仅执行一次
    const debouncedResize = debounce(() => {
      setWindowWidth(window.innerWidth);
    }, 200);

    window.addEventListener('resize', debouncedResize);
    return () => window.removeEventListener('resize', debouncedResize);
  }, []);

  // 根据窗口宽度判断布局
  const isOneColumnLayout = windowWidth < 768;
  const isTwoColumnLayout = windowWidth >= 768 && windowWidth < 1200;

  // ... 上述缓存逻辑
};

// 防抖工具函数
function debounce(func, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 08:57:15