You push one item into an array prop. The component re-renders. Now there are two. Re-render again — three. You stare at the screen, wondering if React is broken.
React is fine. You mutated a prop.
The Bug That Looks Like Magic
You're building a search results component. You want a "Load More" button at the end of the list. Simple enough — just push it onto the results array:
const SearchResults = ({ results }) => {
results.push({ name: "Load More", type: "button" });
return (
<div>
{results.map((result, index) => (
<div key={index}>{result.name}</div>
))}
</div>
);
};First render looks perfect. Second render — two "Load More" buttons. Third — three. The button multiplies like a virus because you're mutating the original array every time the component renders.
Why This Happens
JavaScript passes arrays by reference. When you call .push() on a prop, you're not modifying a local copy. You're reaching back into the parent's data and changing it permanently.
const myArray = [1, 2, 3];
const mutateArray = (arr) => {
arr.push(4);
};
mutateArray(myArray);
console.log(myArray); // Output: [1, 2, 3, 4]The parent doesn't know its data changed. React doesn't detect a state update. But the damage is done — and it compounds on every render.
The Fix Takes One Line
Stop mutating. Create a new array instead:
const SearchResults = ({ results }) => {
const newResults = [...results, { name: "Load More", type: "button" }];
return (
<div>
{newResults.map((result, index) => (
<div key={index}>{result.name}</div>
))}
</div>
);
};The spread operator creates a fresh array. The original stays untouched. The bug vanishes.
This isn't just a React rule — it's a JavaScript survival skill. Every .push(), .splice(), or direct property assignment on a prop is a mutation waiting to betray you. The spread operator is your defense.
If you're reaching for .push() inside a component, you're not adding data — you're planting a time bomb.
