Home
React
Performance: Element Optimization
Daniel Nguyen
Daniel Nguyen
July 24, 2025
1 min

Reusing the same React element object can help React skip unnecessary work when its parent re-renders.

1. The Problem: Unnecessary Re-renders

function Message({ greeting }) {
console.log("Rendering Message");
return <div>{greeting}</div>;
}
function Counter() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
<Message greeting="Hello!" />
</>
);
}

Every time count changes, Counter re-renders and creates a new <Message /> element.

Although greeting remains unchanged, Message normally renders again because its parent rendered again.

2. Solution: Reuse the Same JSX Element

const message = <Message greeting="Hello!" />;
function Counter() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
{message}
</>
);
}

Because message references the same React element object across renders, React can skip rendering that subtree when reconciling it.

Important: This works because the element object is reused, not simply because its props are unchanged.

3. Hoist Static JSX

For UI that never depends on component state or props, you can create the element outside the component.

const footer = <Footer />;
function App() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
{footer}
</>
);
}

The Footer element remains the same between renders, allowing React to skip rendering that subtree when appropriate.

4. Memoize Dynamic JSX with useMemo

When JSX depends on values that can change, useMemo can preserve the element object while its dependencies remain unchanged.

function App({ name }) {
const [count, setCount] = useState(0);
const memoFooter = useMemo(
() => <Footer name={name} />,
[name]
);
return (
<>
<button onClick={() => setCount(c => c + 1)}>
Count: {count}
</button>
{memoFooter}
</>
);
}

The element is reused when count changes but name remains the same.

Note that useMemo is a performance optimization, not a semantic guarantee. React may discard its cached value.

5. Alternative: React.memo

You can also memoize the component itself.

const Footer = memo(function Footer({ color, name }) {
return <footer style={{ color }}>Hello {name}</footer>;
});

React can skip rendering Footer when its props are unchanged, even if its parent re-renders.

However, memo does not prevent renders caused by the component’s own state or consumed context changing.


Tags

#ReactPerformance

Share

Daniel Nguyen

Daniel Nguyen

Frontend Developer

Frontend developer specializing in React, Next.js, and JavaScript. Writing practical guides on modern web development at Dev98.

Expertise

React
Next.js
JavaScript
TypeScript
Python

Social Media

githublinkedinyoutubewebsite

Related Posts

React Performance
Performance: Windowing
August 06, 2025
1 min
Dev98

Dev98

React · Next.js · Web development