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

为何React.memo()会持续渲染组件?——关于JavaScript原始值与引用值的疑问

Understanding React.memo() Behavior with Primitive vs. Reference Values

Great question! Your initial understanding is completely correct—the difference in how React.memo() behaves with string props vs. object/array props is directly tied to JavaScript’s primitive vs. reference value handling. Let’s break this down, address your follow-up questions, and clarify why React.memo() is still incredibly useful.

Why the Rendering Difference Happens

JavaScript has two categories of values, and they’re compared very differently:

  • Primitive values (strings, numbers, booleans, null, undefined, Symbol): These are compared by their actual value. When you write const a = "Amr" and const b = "Amr", a === b returns true because their values are identical.
  • Reference values (objects, arrays, functions): These are compared by their memory reference. Even if two objects/arrays have identical content—like const obj1 = { firstName: "Amr" } and const obj2 = { firstName: "Amr" }—obj1 === obj2 returns false because they’re stored as separate references in memory.

In your experiment:

  • When passing a string prop: The parent component re-renders, but the string value stays the same (same primitive value), so React.memo()’s default shallow comparison detects no change, and the child doesn’t re-render.
  • When passing an object/array prop: Every time the parent re-renders, you create a new object (const name = { firstName: "Amr" }) with a fresh memory reference. Even though the content is identical, React.memo()’s default check looks for matching references (they don’t match), so the child re-renders.

Your custom areEqual function confirms this perfectly: it logs "not equal" for objects/arrays because the references differ, even when their content matches.

Is React.memo() Useless? Absolutely Not!

Your confusion here is totally understandable, but React.memo() is a powerful performance optimization tool—you just need to use it correctly with reference values. Here are common fixes to make it work as intended:

1. Cache Reference Values with useMemo

Wrap your object/array in useMemo to preserve its reference between parent re-renders, unless specific dependencies change:

import { useMemo } from "react";
import Child from "./Child";

export default function App() {
  // Only creates a new object if dependencies (empty array here) change
  const name = useMemo(() => ({ firstName: "Amr" }), []);
  return <Child name={name} />;
}

Now, the name object’s reference stays consistent across parent re-renders, so React.memo() will skip child re-renders unless the object’s content actually changes.

2. Customize the areEqual Comparison

Instead of comparing references, compare the actual content of the props. For your example, update your areEqual function to check the object’s value:

function areEqual(prevProps, nextProps) {
  // Compare the content instead of references
  return prevProps.name.firstName === nextProps.name.firstName;
}

Now, even if the parent passes a new object reference, as long as the firstName value is the same, React.memo() will skip the child re-render.

3. Split Reference Values into Primitive Props

If possible, pass individual primitive values instead of entire objects/arrays. This lets React.memo()’s default comparison work without extra setup:

// Parent component
export default function App() {
  const firstName = "Amr";
  return <Child firstName={firstName} />;
}

// Child component
const Child = ({ firstName }) => {
  return <h2>{firstName}</h2>;
};

export default React.memo(Child);

When to Use React.memo()

It’s most valuable when:

  • Your child component is expensive to render (e.g., complex data visualizations, long lists, or components with heavy calculations).
  • The component receives props that don’t change frequently.

For simple components (like your <h2> example), the performance gain might be negligible, but it’s harmless to use React.memo() anyway.

Final Check

Your core understanding of primitive vs. reference values driving React.memo()’s behavior is 100% correct. The "issue" you noticed is just how JavaScript works—React.memo() doesn’t fail here; it’s following the language’s rules. With the fixes above, you can leverage it to optimize your app’s performance effectively.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:52:46