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

使用React.memo与useCallback阻止InputWithLabel组件重渲染失效问题

问题原因

React.memo 默认对组件的 props 做浅比较,只要有任意一个 props 发生引用层面的变化,就会触发组件重渲染。你点击 Dismiss 触发 App 组件重渲染时,传给 InputWithLabel 的 props 中:

  • id、value(点击Dismiss时searchTerm无变化)、onInputChange(已用useCallback缓存)、isFocused 都是稳定不变的
  • 唯一变化的是 children 属性:你直接在组件中写的 <strong>Search:</strong> 会在每次 App 渲染时生成一个全新的 React 元素对象,引用和上一次渲染的不一样,因此浅比较不通过,触发重渲染。
解决方法

有两种常用方案可选:

方案1:缓存固定的 children 内容

在 App 组件中用 React.useMemo 把固定不变的标签内容缓存起来,保证每次渲染的 children 引用一致:

const App = () => {
  // ...其余原有代码不变
  // 依赖数组为空表示该值永远不会重新计算
  const searchLabel = React.useMemo(() => <strong>Search:</strong>, []);

  return (
    <div>
      <h1>My Hacker Stories</h1>

      <InputWithLabel
        id="search"
        value={searchTerm}
        isFocused
        onInputChange={handleSearch}
      >
        {searchLabel}
      </InputWithLabel>
      {/* ...其余原有代码不变 */}
    </div>
  )
}

方案2:给 React.memo 自定义比较逻辑

如果你能确定 children 永远不会变化,可以给 React.memo 传入第二个参数,自定义 props 比较规则,跳过对 children 的比较:

const InputWithLabel = React.memo(
  // 原有组件定义保持不变
  ({
    id,
    value,
    type = 'text',
    onInputChange,
    isFocused,
    children,
  }) => {
    // ...组件内部原有逻辑不变
  },
  // 自定义比较函数,返回true表示props无变化,不需要重渲染
  (prevProps, nextProps) => {
    return (
      prevProps.id === nextProps.id &&
      prevProps.value === nextProps.value &&
      prevProps.type === nextProps.type &&
      prevProps.onInputChange === nextProps.onInputChange &&
      prevProps.isFocused === nextProps.isFocused
    );
  }
);

两种方案都可以实现点击 Dismiss 删除条目时,InputWithLabel 不会发生不必要的重渲染,若后续存在修改children的需求,优先选择方案1更稳妥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 09:06:04