Mar 10, 2023 - 5 min read
When working with React component, managing data fetching efficiently is crucial to providing a smooth and responsive user experience. In many cases using React.use or React.useEffect for fetching data can lead to multiple redundant requests, impacting both performance and resource usage. In this post, we’ll explore how to implement a custom caching mechanism to prevent unnecessary fetches while using React.Suspense and React.ErrorBoundary to handle loading states and errors.
Using React.use or similar hooks without caching results in repeated network requests, which not only slows down the application but also increases server load.
A caching system can store and reuse promises to prevent redundant fetches. Below is an example of a simple caching class and how it integrates into a React component.
1interface User {
2 id: number;
3 name: string;
4 username: string;
5 email: string;
6 phone: string;
7 website: string;
8}
9
10class Cache<T> {
11 private cache = new Map<string, Promise<T>>();
12
13 async fetch(key: string, fetcher: () => Promise<T>): Promise<T> {
14 if (!this.cache.has(key)) {
15 try {
16 this.cache.set(key, fetcher());
17 } catch (error) {
18 this.cache.delete(key);
19 throw error;
20 }
21 }
22 return this.cache.get(key)!;
23 }
24
25 clear() {
26 this.cache.clear();
27 }
28}
29
1export interface User {
2 id: number;
3 name: string;
4 username: string;
5 email: string;
6 phone: string;
7 website: string;
8}
9
10const userCache = new Cache<User>();
11export function UserProfile({ username }: { username: string }) {
12 // Use the cache to fetch the user data and store it for preventing unnecessary fetches
13 const user = use(userCache.fetch(username, () => fetchUser(username)));
14 return (
15 <div className="p-4 bg-white rounded-lg shadow-md">
16 <h2 className="text-2xl font-bold mb-4">{user.name}</h2>
17 <div className="space-y-2">
18 <p>
19 <span className="font-semibold">Username:</span> {user.username}
20 </p>
21 <p>
22 <span className="font-semibold">Email:</span> {user.email}
23 </p>
24 <p>
25 <span className="font-semibold">Phone:</span> {user.phone}
26 </p>
27 <p>
28 <span className="font-semibold">Website:</span> {user.website}
29 </p>
30 </div>
31 </div>
32 );
33}