Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Windows Tipps & SecurityGetting Repeated No Caller ID Calls? Here’s What’s Really Going On(22.09.2026 um 22:31 Uhr)
Windows Tipps & SecurityHöllenmaschine: Gaming-Peripherie für gut 1.800 Euro für die HMX 6(23.09.2026 um 10:20 Uhr)
Windows Tipps & SecurityDas nächste große Ding: KI-Agenten(23.09.2026 um 10:30 Uhr)
Sichere ProgrammierungHow AI Is Making Restaurant Menus Easier to Navigate(23.09.2026 um 10:55 Uhr)
Windows Tipps & SecurityGetting Repeated No Caller ID Calls? Here’s What’s Really Going On(22.09.2026 um 22:31 Uhr)
Windows Tipps & SecurityHöllenmaschine: Gaming-Peripherie für gut 1.800 Euro für die HMX 6(23.09.2026 um 10:20 Uhr)
Windows Tipps & SecurityDas nächste große Ding: KI-Agenten(23.09.2026 um 10:30 Uhr)
Sichere ProgrammierungHow AI Is Making Restaurant Menus Easier to Navigate(23.09.2026 um 10:55 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Referential Equality & Memoization: Why `{} !== {}` Breaks React Performance

You've probably seen code like this in React: <ChildComponent config={{ theme: 'dark' }} /> And wondered why ChildComponent re-renders on every parent render, even when wrapped in React.memo. Or you've used useEffect and…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

You've probably seen code like this in React:




<ChildComponent config={{ theme: 'dark' }} />






And wondered why ChildComponent re-renders on every parent render, even when wrapped in React.memo.



Or you've used useEffect and seen it run repeatedly:




useEffect(() => {
fetchData();
}, [config]); // 'config' is recreated every render!






The culprit? Referential equality — JavaScript's way of comparing objects and arrays by reference, not by value.



Understanding this is critical for writing performant React applications.






The Golden Rule



In JavaScript, objects and arrays are compared by reference (memory address), not by value. Two objects with identical contents are NOT equal if they're different instances. This means {} !== {} and [] !== []. React uses referential equality to determine when to re-render components, so creating new objects/arrays on every render can cause unnecessary re-renders.



In simpler terms: JavaScript doesn't care if two objects look the same — it only cares if they're the SAME object in memory.



Let's understand why this matters and how memoization solves it.









Part 1: Referential Equality Explained






Primitives vs Objects



Primitives (numbers, strings, booleans, null, undefined) are compared by value:




const a = 5;
const b = 5;
console.log(a === b); // true

const str1 = 'hello';
const str2 = 'hello';
console.log(str1 === str2); // true






Objects (including arrays, functions) are compared by reference:




const obj1 = { name: 'Alice' };
const obj2 = { name: 'Alice' };
console.log(obj1 === obj2); // false (different references!)

const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
console.log(arr1 === arr2); // false






Why? obj1 and obj2 are stored at different memory addresses, even though they have identical contents.









What About Same Reference?






const obj1 = { name: 'Alice' };
const obj2 = obj1; // Same reference

console.log(obj1 === obj2); // true (same memory address)

obj2.name = 'Bob';
console.log(obj1.name); // "Bob" (mutation affects both!)






Key Point: When you assign an object to another variable, you're copying the reference, not the object itself. (See the "Pass by Value" article for more on this!)









Part 2: How This Affects React



React uses referential equality to determine if props have changed:






Example: React.memo Doesn't Work






function Child({ config }) {
console.log('Child rendered');
return <div>{config.theme}</div>;
}

const MemoizedChild = React.memo(Child);

function Parent() {
const [count, setCount] = useState(0);

const config = { theme: 'dark' }; // New object every render!

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedChild config={config} />
</div>
);
}






Result: Every time you click the button, MemoizedChild re-renders, even though React.memo is supposed to prevent that.



Why?




  1. Clicking the button triggers Parent to re-render


  2. const config = { theme: 'dark' } creates a new object

  3. React compares the old and new config props: oldConfig === newConfig → false

  4. React thinks the props changed, so it re-renders MemoizedChild









The Same Problem with Arrays






function Parent() {
const [count, setCount] = useState(0);

const items = [1, 2, 3]; // New array every render!

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedList items={items} />
</div>
);
}






Same issue: items is a new array on every render, so MemoizedList always re-renders.









And Functions Too!






function Parent() {
const [count, setCount] = useState(0);

const handleClick = () => { // New function every render!
console.log('Clicked');
};

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedButton onClick={handleClick} />
</div>
);
}






Same issue: handleClick is a new function on every render.









Part 3: Memoization to the Rescue



Memoization is the technique of caching values/computations so they're only recalculated when dependencies change.



React provides three hooks for memoization:





  1. useMemo — Memoize values (objects, arrays, expensive computations)


  2. useCallback — Memoize functions (special case of useMemo)


  3. React.memo — Memoize entire components









1. useMemo for Objects and Arrays






function Parent() {
const [count, setCount] = useState(0);

const config = useMemo(() => ({ theme: 'dark' }), []); // Same object every render!

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedChild config={config} />
</div>
);
}






How it works:





  • useMemo returns the same object ({ theme: 'dark' }) on every render

  • The object is only recreated if dependencies change (empty array [] = never)

  • Now oldConfig === newConfig → true, so MemoizedChild doesn't re-render









With Dependencies






function Parent({ theme }) {
const [count, setCount] = useState(0);

const config = useMemo(() => ({ theme }), [theme]); // Recreate only when 'theme' changes

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedChild config={config} />
</div>
);
}






Now:




  • When count changes, config stays the same (no re-render)

  • When theme changes, config is recreated (re-render happens, as expected)









2. useCallback for Functions



useCallback is shorthand for memoizing functions:




function Parent() {
const [count, setCount] = useState(0);

const handleClick = useCallback(() => { // Same function every render!
console.log('Clicked');
}, []); // No dependencies = function never changes

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedButton onClick={handleClick} />
</div>
);
}






Equivalent useMemo version:




const handleClick = useMemo(() => {
return () => console.log('Clicked');
}, []);






But useCallback is cleaner for functions.









With Dependencies






function Parent({ userId }) {
const [count, setCount] = useState(0);

const handleClick = useCallback(() => {
console.log(`Clicked for user ${userId}`);
}, [userId]); // Recreate when 'userId' changes

return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<MemoizedButton onClick={handleClick} />
</div>
);
}












3. React.memo for Components



React.memo is a Higher-Order Component that memoizes the entire component:




const Child = React.memo(function Child({ config }) {
console.log('Child rendered');
return <div>{config.theme}</div>;
});






How it works:




  • React shallowly compares old and new props

  • If all props are referentially equal, skip re-render

  • If any prop changes (by reference), re-render



Important: React.memo uses shallow comparison:




// Shallow comparison (default)
oldProps.config === newProps.config // Checks reference only

// Deep comparison (custom)
React.memo(Child, (prevProps, nextProps) => {
return prevProps.config.theme === nextProps.config.theme; // Custom logic
});












Part 4: When to Use Memoization






Use Memoization When:




  1. Passing objects/arrays to memoized child components




const config = useMemo(() => ({ theme: 'dark' }), []);
<MemoizedChild config={config} />







  1. Passing functions to memoized child components




const handleClick = useCallback(() => {}, []);
<MemoizedButton onClick={handleClick} />







  1. Expensive computations




const sortedData = useMemo(() => {
return data.sort((a, b) => a.value - b.value); // Expensive!
}, [data]);







  1. Dependencies in useEffect or other hooks




const config = useMemo(() => ({ theme: 'dark' }), []);

useEffect(() => {
fetchData(config); // Won't re-run unnecessarily
}, [config]);












Don't Use Memoization When:




  1. Primitives (already compared by value)




// Unnecessary
const count = useMemo(() => 5, []);

// Just use the value
const count = 5;







  1. Child doesn't re-render expensively




// Overkill if rendering <div>{text}</div> is cheap
const text = useMemo(() => someString, []);







  1. Component always re-renders anyway




// No benefit if Child isn't memoized
const config = useMemo(() => ({ theme: 'dark' }), []);
<Child config={config} /> // Not wrapped in React.memo







  1. Premature optimization



Don't memoize everything! Only optimize when you have a performance problem.









Part 5: Common Memoization Pitfalls






Pitfall 1: Missing Dependencies






function Component({ userId }) {
const handleClick = useCallback(() => {
console.log(`User: ${userId}`); // Uses 'userId'
}, []); // Missing dependency!

return <button onClick={handleClick}>Click</button>;
}






Problem: handleClick closes over the initial userId and never updates.



Fix:




const handleClick = useCallback(() => {
console.log(`User: ${userId}`);
}, [userId]); // Include 'userId'












Pitfall 2: Memoizing Without Memoized Child






function Parent() {
const config = useMemo(() => ({ theme: 'dark' }), []); // Useless!

return <Child config={config} />; // Child isn't memoized
}

function Child({ config }) {
return <div>{config.theme}</div>;
}






Problem: Child re-renders on every Parent render anyway (not wrapped in React.memo).



Fix:




const MemoizedChild = React.memo(Child); // Now useMemo helps

function Parent() {
const config = useMemo(() => ({ theme: 'dark' }), []);
return <MemoizedChild config={config} />;
}












Pitfall 3: Creating Objects Inside JSX






function Parent() {
return <Child config={{ theme: 'dark' }} />; // New object every render!
}






Fix:




function Parent() {
const config = useMemo(() => ({ theme: 'dark' }), []);
return <Child config={config} />; // Stable reference
}












Pitfall 4: Memoizing Everything (Over-Optimization)






// Too much memoization
function Component() {
const a = useMemo(() => 1, []);
const b = useMemo(() => 2, []);
const sum = useMemo(() => a + b, [a, b]);

return <div>{sum}</div>;
}






Problem: useMemo has overhead. For simple computations, it's slower than just recalculating.



Better:




function Component() {
const a = 1;
const b = 2;
const sum = a + b; // Fast enough without memoization

return <div>{sum}</div>;
}












Part 6: Memoization Patterns in React






Pattern 1: Memoizing Context Values






function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');

// New object every render → all consumers re-render!
// const value = { theme, setTheme };

// Stable reference
const value = useMemo(() => ({ theme, setTheme }), [theme]);

return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
}












Pattern 2: Memoizing Expensive Filters






function UserList({ users, filter }) {
const filteredUsers = useMemo(() => {
return users.filter(user => {
// Expensive filtering logic
return user.name.toLowerCase().includes(filter.toLowerCase());
});
}, [users, filter]); // Only recompute when 'users' or 'filter' changes

return (
<ul>
{filteredUsers.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}












Pattern 3: Memoizing Event Handlers with Parameters






function ItemList({ items, onDelete }) {
return (
<ul>
{items.map(item => (
<Item key={item.id} item={item} onDelete={onDelete} />
))}
</ul>
);
}

const Item = React.memo(function Item({ item, onDelete }) {
// New function every render
// const handleDelete = () => onDelete(item.id);

// Memoized
const handleDelete = useCallback(() => {
onDelete(item.id);
}, [item.id, onDelete]);

return (
<li>
{item.name}
<button onClick={handleDelete}>Delete</button>
</li>
);
});












Pattern 4: Using Refs for Stable References



Sometimes you need a value that doesn't trigger re-renders:




function Component() {
const configRef = useRef({ theme: 'dark' });

useEffect(() => {
// Always uses the same object reference
fetchData(configRef.current);
}, []); // No dependencies needed

return <div>Content</div>;
}






Use case: When you need a stable reference but don't want to trigger re-renders when it changes.









Part 7: Debugging Referential Equality






Tool 1: Object.is() (React's Comparison)



React uses Object.is() for comparison (similar to === but handles NaN correctly):




const obj1 = { theme: 'dark' };
const obj2 = { theme: 'dark' };

console.log(Object.is(obj1, obj2)); // false (different references)

const obj3 = obj1;
console.log(Object.is(obj1, obj3)); // true (same reference)












Tool 2: React DevTools Profiler



Use the React DevTools Profiler to see why components re-render:




  1. Open React DevTools

  2. Go to Profiler tab

  3. Start recording

  4. Interact with your app

  5. Look at "Why did this render?" section









Tool 3: useWhyDidYouUpdate Hook (Custom)






function useWhyDidYouUpdate(name, props) {
const previousProps = useRef();

useEffect(() => {
if (previousProps.current) {
const allKeys = Object.keys({ ...previousProps.current, ...props });
const changedProps = {};

allKeys.forEach(key => {
if (previousProps.current[key] !== props[key]) {
changedProps[key] = {
from: previousProps.current[key],
to: props[key]
};
}
});

if (Object.keys(changedProps).length) {
console.log('[why-did-you-update]', name, changedProps);
}
}

previousProps.current = props;
});
}

function MyComponent(props) {
useWhyDidYouUpdate('MyComponent', props);
return <div>Content</div>;
}












Quick Reference Cheat Sheet

































Hook Purpose Example
useMemo Memoize values (objects, arrays, computations) useMemo(() => ({ theme }), [theme])
useCallback Memoize functions useCallback(() => {}, [deps])
React.memo Memoize components React.memo(Component)
useRef Stable mutable reference (doesn't cause re-renders) useRef({ theme: 'dark' })








Key Takeaways



Objects and arrays are compared by reference, not by value: {} !== {}

Creating objects/arrays/functions on every render causes unnecessary re-renders in memoized components

useMemo stabilizes object/array references across renders

useCallback stabilizes function references (shorthand for useMemo with functions)

React.memo prevents component re-renders when props don't change (by reference)

Always include dependencies in useMemo and useCallback

Don't memoize primitives — they're already compared by value

Memoize context values to prevent unnecessary consumer re-renders

Don't over-optimize — memoization has overhead, only use it when needed









Interview Tip



When asked about referential equality and memoization:




  1. "In JavaScript, objects are compared by reference, not value, so {} !== {} even though they look identical"

  2. React's impact: "React uses referential equality to check if props changed. If you create a new object on every render, React thinks the props changed, causing re-renders"

  3. Solution: "useMemo and useCallback stabilize references across renders, preventing unnecessary re-renders in memoized components"

  4. Example: "If you pass config={{ theme: 'dark' }} to a memoized child, it re-renders every time. Using useMemo(() => ({ theme: 'dark' }), []) fixes it"

  5. Best practice: "Only memoize when you have a performance problem — measure first, optimize second"



Now go forth and never wonder why your memoized component keeps re-rendering again!h

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Referential Equality & Memoization: Why `{} !== {}` Breaks React Performance

Thematisch verwandte Begriffe: Referential, Equality, Memoization, Breaks · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-96258 | A vulnerability has been found in onSite internet GmbH Auktion NG Auktio…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick