Description

Fetching data efficiently is one of the most important performance optimizations in modern React apps.

In this challenge, you’ll build a custom React hook that fetches data from an API and caches the response in memory, so repeated requests for the same URL don’t trigger redundant network calls.

Your goal is to create a hook called useFetchWithCache that manages loading state, caching, and error handling — all within a clean, reusable API.


Requirements

Hook Definition

Create a hook named useFetchWithCache(url).

It should return an object with:

{
data,
loading,
error,
invalidateCache
}

Caching Behavior

Cache API responses in memory using a shared object or Map.

When the same URL is requested again, serve the cached response instantly instead of refetching.

Parallel Requests

If multiple components call the hook with the same URL at the same time:

Only one network request should be made.

All components should receive the same data once it resolves.

Cache Invalidation

Return a function invalidateCache() from the hook.

When called:

It should clear the cached data for that specific URL.

The next hook call (or rerender) should trigger a fresh fetch from the API.


Example Usage

function UserList() {
const { data, loading, error, invalidateCache } = useFetchWithCache(
'https://jsonplaceholder.typicode.com/users'
);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
<div>
<ul>
{data.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>

<button onClick={invalidateCache} className="mt-2 px-3 py-1 bg-red-500 text-white rounded">
Refresh Data
</button>
</div>
);
}

Example Behavior

Action

Expected Result

First call to /users

Data fetched from API

Second call to /users

Data served instantly from cache

Two components request /users simultaneously

Only one fetch request is made

Call invalidateCache()

Cache cleared and next render refetches data

Hints

Hint 1

You can use a Map or plain object for caching responses.

Hint 2

Consider using a shared store outside the hook scope for global caching.

Hint 3

Handle race conditions when multiple components call the same URL concurrently.