React is a powerful library, but it can be incredibly frustrating when you update the state, and absolutely nothing happens on the screen.
I have spent countless hours debugging components that seemed perfectly fine, only to realize I was making a fundamental mistake with how React tracks changes.
In this guide, I will show you exactly why your React components are staying static and how you can trigger those elusive re-renders every single time.
React Rendering Cycle
Before we dive into the fixes, it is important to understand that React is quite picky about how it detects changes.
React uses a virtual DOM to compare the old state with the new state. If it thinks nothing has changed, it simply skips the render to save performance.
Most of the time, when a component fails to update, it is because you have accidentally “tricked” React into thinking the state is still the same.
Method 1: Avoid Direct State Mutation (The Most Common Culprit)
One of the first things I learned as a developer is that you should never mutate state directly.
If you are working with an array of US Zip Codes and you use .push(), React won’t see that as a change because the memory reference remains the same.
The Problematic Code
In this example, I am trying to add a new California zip code to a list, but the UI won’t update because I’m mutating the original array.
import React, { useState } from 'react';
const ZipCodeTracker = () => {
const [zipCodes, setZipCodes] = useState(['90210', '94105']);
const addZipCode = () => {
// This is a direct mutation!
zipCodes.push('92101');
setZipCodes(zipCodes);
console.log(zipCodes); // The array grows, but the UI stays the same
};
return (
<div style={{ padding: '20px' }}>
<h1>California Zip Code Registry</h1>
<ul>
{zipCodes.map(zip => <li key={zip}>{zip}</li>)}
</ul>
<button onClick={addZipCode}>Add San Diego Zip</button>
</div>
);
};
export default ZipCodeTracker;You can see the output in the screenshot below.

The Correct Way (Using the Spread Operator)
To fix this, I always create a new copy of the array. This changes the reference, telling React that it’s time to re-render.
import React, { useState } from 'react';
const ZipCodeTracker = () => {
const [zipCodes, setZipCodes] = useState(['90210', '94105']);
const addZipCode = () => {
// I am creating a brand new array here
setZipCodes([...zipCodes, '92101']);
};
return (
<div style={{ padding: '20px' }}>
<h1>California Zip Code Registry</h1>
<ul>
{zipCodes.map(zip => <li key={zip}>{zip}</li>)}
</ul>
<button onClick={addZipCode}>Add San Diego Zip</button>
</div>
);
};
export default ZipCodeTracker;Method 2: Update Nested Objects Correctly
Handling nested objects, like a user profile for a US-based e-commerce site, can be tricky. If you only update a deep property, React’s “shallow comparison” will miss it.
The Wrong Way to Update Objects
Here, I try to update the street address of a customer in New York, but the component remains stuck on the old data.
import React, { useState } from 'react';
const CustomerProfile = () => {
const [customer, setCustomer] = useState({
name: 'John Doe',
location: {
city: 'New York',
state: 'NY',
street: '5th Ave'
}
});
const updateStreet = () => {
// This only changes a property, not the object reference
customer.location.street = 'Wall Street';
setCustomer(customer);
};
return (
<div style={{ padding: '20px' }}>
<h2>Customer Shipping Info</h2>
<p>City: {customer.location.city}</p>
<p>Street: {customer.location.street}</p>
<button onClick={updateStreet}>Move to Wall Street</button>
</div>
);
};
export default CustomerProfile;The Correct Way (Deep Copying)
I make sure to spread both the top-level object and the nested object to ensure React detects the change.
import React, { useState } from 'react';
const CustomerProfile = () => {
const [customer, setCustomer] = useState({
name: 'John Doe',
location: {
city: 'New York',
state: 'NY',
street: '5th Ave'
}
});
const updateStreet = () => {
setCustomer({
...customer,
location: {
...customer.location,
street: 'Wall Street'
}
});
};
return (
<div style={{ padding: '20px' }}>
<h2>Customer Shipping Info</h2>
<p>City: {customer.location.city}</p>
<p>Street: {customer.location.street}</p>
<button onClick={updateStreet}>Move to Wall Street</button>
</div>
);
};
export default CustomerProfile;You can see the output in the screenshot below.

Method 3: Handle State Updates that Depend on Previous State
Sometimes, re-renders fail or behave strangely because of how React batches updates. If you are calculating a tax rate or a stock count, you should use a functional update.
Use the Functional Update Pattern
In this example, I am calculating the total cost of a Starbucks order in Chicago including tax.
import React, { useState } from 'react';
const StarbucksOrder = () => {
const [total, setTotal] = useState(5.00);
const applyTax = () => {
// Using the previous state ensures accuracy
setTotal((prevTotal) => prevTotal + (prevTotal * 0.1025));
};
return (
<div style={{ padding: '20px' }}>
<h3>Chicago Order Total (incl. 10.25% Tax)</h3>
<p>Current Total: ${total.toFixed(2)}</p>
<button onClick={applyTax}>Calculate Final Bill</button>
</div>
);
};
export default StarbucksOrder;You can see the output in the screenshot below.

Method 4: Ensure Keys are Unique in Lists
When rendering lists of data, such as a list of US States, using the array index as a key is a recipe for disaster.
If the order of the list changes, React might get confused and fail to update the DOM correctly.
Proper Key Usage Example
I always use a unique ID, like an ISO code, to help React track which items have actually changed.
import React, { useState } from 'react';
const StateList = () => {
const [states, setStates] = useState([
{ id: 'TX', name: 'Texas' },
{ id: 'FL', name: 'Florida' }
]);
const addState = () => {
setStates([{ id: 'AK', name: 'Alaska' }, ...states]);
};
return (
<div style={{ padding: '20px' }}>
<ul>
{states.map((st) => (
<li key={st.id}>{st.name}</li>
))}
</ul>
<button onClick={addState}>Add Alaska to Top</button>
</div>
);
};
export default StateList;Method 5: Use Forces via the ‘key’ Prop
If you have a complex third-party component (like a Google Map or a specialized US Census chart) that refuses to update, you can force it to re-mount.
I do this by changing the key prop of the component itself.
import React, { useState } from 'react';
const WeatherWidget = ({ city }) => {
return <div>Current weather in {city} is Sunny.</div>;
};
const WeatherDashboard = () => {
const [city, setCity] = useState('Miami');
const [version, setVersion] = useState(0);
const refreshData = () => {
setCity('Seattle');
setVersion(v => v + 1); // Changing the key forces a full re-render
};
return (
<div style={{ padding: '20px' }}>
<WeatherWidget key={version} city={city} />
<button onClick={refreshData}>Switch to Seattle</button>
</div>
);
};
export default WeatherDashboard;Things to Check if it Still Won’t Render
If you have tried the methods above and your component is still stubborn, check these three things:
- Strict Mode: In Development, React Strict Mode renders components twice to find bugs. Sometimes this masks or highlights state issues.
- Prop Drilling: Ensure the state is actually being passed down to the child component as a prop.
- Memoization: If you are using React.memo or useMemo, you might be blocking a render because your dependency array is incorrect.
I highly recommend using the React DevTools browser extension. It has a “Highlight updates when components render” feature that is a lifesaver.
In this tutorial, I have covered the most common reasons why a React component might not re-render after a state update.
Whether it is a simple array mutation or a complex nested object, the key is always to provide React with a new memory reference.
You may also like to read:
- How to Convert React Component to Web Component
- Build React Code Snippet Component
- How to Create a Retool Custom React Component
- How to Get Component Width in React

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.