Programming
EN
1 min read
reverse() in React can surprise you — here’s why (and how to fix it)
Don’t let reverse() backfire in React

Array.prototype.reverse() mutates the original array. That’s fine in isolated scripts, but inside a React render it can lead to surprising UI, especially in React 18 Strict Mode (development) where React intentionally invokes render twice to surface side effects.The surprising behaviorThe surprising behavior
The surprising behaviorThe surprising behavior
Consider a parent passing an array as props:
jsx
// Parent.jsx export default function Parent() { const items = [1, 2, 3]; // imagine this actually comes from state/props return <Products items={items} />; }
And the child mutates that array during render:
jsx
// Products.jsx (❌ anti-pattern) export function Products({ items }) { return <ul>{items.reverse().map(i => <li key={i}>{i}</li>)}</ul>; }
In
Strict Mode (dev only), React calls your component function twice; the first render is discarded, but your side-effect (mutating items) is not. So:- 1. First render:
- 2. Second render receives the same array reference (already mutated) and calls
- 3. The committed UI shows
Even outside
Strict Mode, mutating props/state in render is still an anti-pattern: it breaks render purity, can cause flickers on re-renders, and ruins memoization.The correct pattern: don’t mutateThe correct pattern: don’t mutate
The correct pattern: don’t mutateThe correct pattern: don’t mutate
Use a non-mutating approach:
ES2023 (recommended):ES2023 (recommended):
ES2023 (recommended):ES2023 (recommended):
js
export function Products({ items }) { return <ul>{items.toReversed().map(i => <li key={i}>{i}</li>)}</ul>; }
Pre-ES2023 (clone, then reverse)Pre-ES2023 (clone, then reverse)
Pre-ES2023 (clone, then reverse)Pre-ES2023 (clone, then reverse)
js
export function Products({ items }) { return <ul>{items.slice().reverse().map(i => <li key={i}>{i}</li>)}</ul>; // or: [...items].reverse() }
If the list is large and
items changes infrequently, you can memoize:jsx
import { useMemo } from "react"; export function Products({ items }) { const reversed = useMemo(() => items.toReversed(), [items]); return <ul>{reversed.map(i => <li key={i}>{i}</li>)}</ul>; }
As simple as that to keep your component pure and predictable.
Hope this helps!
