New Jul 31, 2026

React use() cache gets overwritten by an older Promise after invalidation

Libraries, Frameworks, etc. All from Newest questions tagged reactjs - Stack Overflow View React use() cache gets overwritten by an older Promise after invalidation on stackoverflow.com

I am using React 19.2 with Vite.

I am playing around with a small Promise cache for React 19 use() and I cannot figure out the best way to handle this.

So I start with one request and it takes 1.5 seconds. Before it finishes I delete the cache entry, change the value from Nicole to David and trigger another render.

The second request finishes first and puts David in the cache (which is what I want).

The problem is the first request is still running. When it finally finishes it puts Nicole back in the cache and overwrites the newer result.

So it ends up doing this:

Request 2 cached David
Request 1 cached Nicole

Then the next render reads Nicole again.

I know I could cancel an order fetch request with AbortController but the real async operation may not always be something I can cancel.

I believe I need to check that the Promise still belongs to the current cache entry before letting it update the cache.

Like:

if (userCache.get(id) === entry) {
 // update the cache
}

I am probably missing something simple, but I am not sure how to set up the entry so I can reference it inside the Promise callback without messing up the stable Promise that use() needs.

What is the best way to handle this?

To reproduce it click Rename to David and invalidate before the first request finishes. Wait for both requests and then click Render again.

import {
 Suspense,
 startTransition,
 use,
 useState
} from "react";

const userCache = new Map();

let serverName = "Nicole"; let requestCount = 0;

function fetchUser(id) { const requestId = ++requestCount; const name = serverName; const delay = requestId === 1 ? 1500 : 100;

return new Promise((resolve) => { setTimeout(() => { resolve({ id, name, requestId }); }, delay); }); }

function getUser(id) { let entry = userCache.get(id);

if (!entry) { const promise = fetchUser(id).then((user) => { userCache.set(id, { promise: Promise.resolve(user) });

console.log( Request ${user.requestId} cached ${user.name} );

return user; });

entry = { promise }; userCache.set(id, entry); }

return entry.promise; }

function User({ id, revision }) { const user = use(getUser(id));

return ( <p> {user.name} from request {user.requestId} </p> ); }

export default function App() { const [revision, setRevision] = useState(0);

function renameAndInvalidate() { serverName = "David"; userCache.delete(1);

startTransition(() => { setRevision((value) => value + 1); }); }

function renderAgain() { setRevision((value) => value + 1); }

return ( <> <button onClick={renameAndInvalidate}> Rename to David and invalidate </button>

<button onClick={renderAgain}> Render again </button>

<Suspense fallback={<p>Loading...</p>}> <User id={1} revision={revision} /> </Suspense> </> ); }

Scroll to top