Why does React render an intermediate state between two setState calls? [duplicate]
Why React Displays Intermediate State Between setState Calls ## Introduction During the development of user interfaces, it is common to encounter situations where unexpected intermediate states may appear between...
![Why does React render an intermediate state between two setState calls? [duplicate]](https://api.andrey-dev.online/wp-content/uploads/2026/09/img-43de20e9-1788582319.jpg)
![Why does React render an intermediate state between two setState calls? [duplicate] - image 2](https://api.andrey-dev.online/wp-content/uploads/2026/09/img-d6c5a487-1788582330.jpg)
Why React Displays Intermediate State Between setState Calls
Introduction
During the development of user interfaces, it is common to encounter situations where unexpected intermediate states may appear between calls to setState in React. This can be particularly noticeable on pages where a user performs multiple actions consecutively. In this article, we will explore an example from real-world development related to address search and displaying results.
Implementation Example
Consider the AddressSearch page, which allows users to enter an address, receive suggested options from the Google Maps API, and display the results on the screen. The crucial parts of the code are shown below:
export const useSystemAddressStrategy = ({ companyId, gMaps, initialAddress }: SystemAddressStrategyOptions): StrategyResult => {
// ----- Address
const [addressParams, setAddressParams] = useState<AdvancedSearchAddressPayload & { formattedAddress: string }>(convertToAddressPayload(initialAddress));
// ----- Page
const [page, setPage] = useState<number>(0);
// ----- Sort Direction
const [sortDirection, setSortDirection] = useState<SortDirection>(SortDirection.ASC);
};
Main Actions
- Changing the Address: When the address is changed, all UI data is cleared, a new request is made with the updated address, and the data is displayed.
- Changing Sorting Direction: When the sorting direction is changed, all UI data is also cleared, a new request is made with the updated sorting direction, and the data is displayed.
- Scrolling to the End of the Page: When scrolling to the end of the page, a new API request is made with an incremented page number, and new data is added to the existing data.
Intermediate State Problem
The problem lies in the fact that between calls to setState, an intermediate state may appear that does not match any of the expected states. This happens due to the asynchronous nature of API calls and component state updates.
How It Works
When a user performs an action, such as changing the address, React updates the state and renders the component. However, until the new API request completes and updates the state, the intermediate state may be visible on the screen.
Example
Suppose a user enters a new address. React updates the state and renders the component with a cleared UI. Afterward, an API request is made. Until the request completes, the user may see an intermediate state where some data has already been updated while other data has not.
Solution to the Problem
To avoid intermediate states, various approaches can be used:
1. Using Loading Flags
Add loading flags for each action to display a loading state instead of an intermediate state.
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
if (isLoading) {
return;
}
setIsLoading(true);
fetchNewData()
.then(data => {
// Update state after receiving data
setPage(0);
setAddressParams(convertToAddressPayload(newAddress));
})
.finally(() => setIsLoading(false));
}, [isLoading, newAddress]);
2. Freezing the UI
Freeze the UI during the request and unfreeze it after receiving the data.
const handleAddressChange = (newAddress) => {
setIsLoading(true);
fetchNewData(newAddress)
.then(data => {
setPage(0);
setAddressParams(convertToAddressPayload(newAddress));
})
.finally(() => setIsLoading(false));
};
3. Managing State Inside Functions
Use functional methods to manage state inside event handlers.
const handleAddressChange = (newAddress) => {
const fetchData = async () => {
setIsLoading(true);
await fetchNewData(newAddress);
setPage(0);
setAddressParams(convertToAddressPayload(newAddress));
setIsLoading(false);
};
fetchData();
};
Practical Tips
- Use
useEffectto manage state after API requests. - Add loading flags to display a loading state.
- Freeze the UI during requests.
- Use functional methods to manage state.
Conclusion
Intermediate states between calls to setState can cause problems in React applications. Using loading flags, freezing the UI, and functional methods will help manage state more effectively and avoid unwanted intermediate states.