Empower growth and innovation with the latest Front-end Dev insights

It's 2026 — in React, the faster you switch filters, the more often you see the previous dataset. Is the API returning out of order?

Sep 29, 2026 Read: 46

Bottom line first: in React, the faster you switch filters, the more often you see the previous dataset — most of the time it is not a wrong API response but a request race. The filter you click later does not necessarily return first; when the slower old request comes back, it overwrites the newer result. In 2026, this shows up often in search suggestions, tab filters, and paginated lists. The key is not React itself but whether every request gets an identity and stale responses get discarded.

Why an old request can overwrite new data during fast switching

The order in which the browser sends requests is not the order in which responses come back. CDN hit differences, hot and cold endpoints, weak-network retries, and HTTP/2 multiplexing can all make an earlier request return later. A common React pattern is to fire a request from an event handler or useEffect and call setState directly in then; if you do not record which filter this response belongs to, the old response will also be written into the same piece of state.

Adding loading alone is usually not enough. loading only says that a request is in flight; it does not say which request is the current one. Typical cases include: typing continuously in a search box and a short keyword returning first; switching a tab from Pending payment to Completed, and the old tab's data overwriting the new tab; quickly clicking page 2 and then page 3 in pagination, so the table content no longer matches the page number; switching a detail view from product A to B, and A's price or stock landing first.

How to tell it is a race, not cache or stale state

Race conditions, browser cache, data-fetching library cache, and state placed in the wrong location all look like showing old data on the surface, but the troubleshooting paths differ. A race has a telling feature: slow operations work fine, and it only reproduces with fast consecutive switching; cache often keeps returning the same old value after a refresh, with little relation to how fast you operate.

  1. Fix a reproduction path: switch quickly 5 to 10 times in a row and note which attempt shows old data; if fast switching reproduces it, suspect a race first.
  2. Look at the Network timeline: compare the order requests are sent with the order responses return, then open the response body and check whether old parameters land later than new parameters.
  3. Add a request identifier: log the parameters, requestId, and landing time in then; if the old parameters are written last, it is basically confirmed as a race rather than a cache hit.

Another easily missed point is that a request keeps running after the component unmounts. Newer React versions no longer warn as clearly about setState after unmount, but if the request is not stopped, switching back quickly may write old data into the new page.

A checkable close-out: the four request-timeline checks

Treating a race as a request lifecycle problem is easier to sign off than sprinkling if statements inside then. A common 2026 delivery habit is to check four steps: trigger source, identity, cancellation, and landing.

  1. Trigger source: confirm whether the request is started by a click, a useEffect dependency change, polling, or a route change; unify the entry point first so the same data does not have multiple triggers.
  2. Identity: attach a requestId or a parameter snapshot to each request, and keep the currently valid identity in the component.
  3. Cancellation: cancel the old request with AbortController when possible; for endpoints that cannot be canceled, mark the stale response.
  4. Landing: compare the identity before setState and only handle a result that matches the current identity; clean up in cleanup when the component unmounts or dependencies change.

Acceptance can be written as a checkable list: after 10 fast consecutive switches, the content matches the current selection; old requests in Network show as canceled or stale; on error or timeout the UI enters an explicit error or empty state and does not keep the previous data; after switching away and back, the filter conditions and list content stay in sync. This is easier to regress than \"it looks fine.\"

Comparison of common approaches and their experience ranges

Canceling requests, marking them stale, or handing the job to a data-fetching library has no absolute best answer. The comparison below is organized by applicable object, experience range, and boundaries; the durations are only typical ranges, so defer to project complexity.

  • AbortController + useEffect cleanup: suits native fetch, low request volume, and lists and filters sharing one request function. The change is concentrated in the request layer, with an experience range of about 0.5–1 person-day. The boundary is that when a legacy endpoint or third-party SDK does not accept a signal, you have to fall back to stale marking.
  • requestId or parameter snapshot comparison: suits axios projects, endpoints that are inconvenient to cancel, and multiple components sharing one request function. The experience range is about 0.5–1 person-day, but new call sites must remember to compare the identity, which is easy to miss.
  • Data-fetching libraries such as React Query and SWR: suit projects with many requests, complex caching, and concurrent pagination and filtering. The library handles caching, deduplication, and part of the race problem, but you are still responsible for the query key design; the experience range for introduction and migration is about 3–5 person-days, plus the cost of the team getting familiar with it.

On the delivery floor: how stale data gets exposed during fast filter switching

In one list-page project, the constraints were typical: two rounds of joint debugging, a third-party endpoint, no easy way to add cancellation logic, and filter parameters that changed often. The approach was to add a requestId in the request layer, mark stale responses in useEffect cleanup, and simply discard responses for endpoints that could not be wired to AbortController in time. After launch, users still reported that \"switching fast shows the previous dataset.\" Investigation found that the pagination component sent its own requests and did not go through the same request layer; only after filters and pagination were unified into one entry point did it stabilize. The cost was about half a day to a day of rework plus another regression round; if the unified entry point had followed the four checks from the start, that cost could have been saved within the typical range. When the team delivers website and H5 interaction work, this is also on the joint-debugging checklist to avoid discovering it from user feedback after launch.

When it applies and when it does not

Race-condition close-out suits pages with \"frequent switching + a shared data landing spot,\" such as search suggestions, tab filters, paginated lists, fast detail switching, and dashboards refreshing multiple cards. The test is: the user can start the next request of the same kind before the previous one returns, and the two results are written into the same piece of UI.

The cases where it does not apply, or does not need to be added, are just as clear: one-time static data, form submissions, backends that already return only the latest result by version number, or switching that navigates to a separate page and does not share a data landing spot. The boundary can be remembered as one sentence: for read APIs with concurrent switching, handle the race first; for write APIs and one-time loads, ensure idempotency and error handling first.

FAQ

If I send requests in useEffect, do I always need to write cleanup to cancel them?

Not necessarily. When a request result is only written into an unmounted component, cancellation reduces wasted updates; if the page does not switch fast, the impact is limited. The common 2026 practice is still to add it, since the cost is low.

Will the previous data still show when using React Query?

Yes. React Query handles caching and deduplication, but if the query key does not include the filter parameters, or placeholder data is configured poorly, switching can still briefly show old data. Check queryKey first.

Why does stale data still flash after adding loading?

loading only controls visibility; it does not control which response lands. An old request that returns later will still be written into state, so you need a requestId or a cancellation mechanism to stop it, not loading alone.

Should I use AbortController or axios CancelToken?

Use AbortController when you can; it is the platform standard, and newer axios versions support signal too. CancelToken is the older interface, so legacy projects can maintain it according to team conventions.


If a project already shows old data during fast switching, walk the four request-timeline checks from trigger source to landing, then close out cancellation or stale marking into a unified request layer. It suits pages with frequent concurrent switching and a shared data landing spot in the UI; static display pages and endpoints where the backend already returns the latest result by version do not need an extra data-fetching library. Following 2026 delivery habits, validate with a small change first, then decide whether to adopt the full approach.

Have a similar project in mind?
Contact us for a one-to-one project reference proposal
Obtain Proposal
Interested in this topic?
10-year tech team — reference proposal within 24 hours
Obtain Proposal
Are you ready?
Then reach out to us!
+86-13370032918
Discover more services, feel free to contact us anytime.
Please fill in your requirements
What services would you like us to provide for you?
Your Budget
ct.
Our WeChat
Professional technical solutions
Phone
+86-13370032918 (Manager Jin)
The phone is busy or unavailable; feel free to add me on WeChat.
E-mail
349077570@qq.com
Submitted successfully
Thank you for your trust. We will contact you soon!
Recommended projects for you