Access data already fetched with react query in other component

2 min read 05-10-2024
Access data already fetched with react query in other component


Accessing Fetched Data Across Components with React Query

React Query is a powerful library for fetching, caching, and managing asynchronous data in React applications. But what if you need to access data fetched in one component within another component? This is a common scenario, and React Query provides elegant solutions to handle this efficiently.

The Problem: Data Silos

Imagine you have a component that fetches a list of users from an API using React Query. You might want to display these users in another component, like a user profile page. However, without proper handling, the user data is effectively "isolated" within the component that fetched it.

Example:

// UserList.js
import { useQuery } from 'react-query';

const UserList = () => {
  const { isLoading, error, data: users } = useQuery('users', () => fetchUsers());

  // ... render users list ...
};

// UserProfile.js
const UserProfile = ({ userId }) => {
  // ... how to access user data from UserList here? ...
};

In this example, UserList fetches users and displays them. But UserProfile has no access to the fetched user data.

Solutions: Breaking Down Data Silos

React Query provides several ways to share data across components:

1. Context API:

The Context API allows you to create a global data "store" accessible throughout your application.

// UserContext.js
import React, { createContext, useContext } from 'react';

const UserContext = createContext();

const UserProvider = ({ children }) => {
  const { isLoading, error, data: users } = useQuery('users', () => fetchUsers());

  return (
    <UserContext.Provider value={{ users }}>
      {children}
    </UserContext.Provider>
  );
};

// UserProfile.js
const UserProfile = ({ userId }) => {
  const { users } = useContext(UserContext);
  const user = users.find(user => user.id === userId);

  // ... render user profile ...
};

Here, UserProvider provides the fetched users through the context. UserProfile can then access the context and retrieve the relevant user.

2. Custom Hooks:

Create a reusable custom hook to fetch the data and return it:

// useUsers.js
import { useQuery } from 'react-query';

const useUsers = () => {
  const { isLoading, error, data: users } = useQuery('users', () => fetchUsers());
  return { isLoading, error, users };
};

// UserList.js
const UserList = () => {
  const { isLoading, error, users } = useUsers();

  // ... render users list ...
};

// UserProfile.js
const UserProfile = ({ userId }) => {
  const { users } = useUsers();
  const user = users.find(user => user.id === userId);

  // ... render user profile ...
};

This hook centralizes the fetching logic and provides the data to both components, enhancing code reusability.

3. Shared Query Keys:

When using useQuery with the same query key in different components, React Query automatically caches and shares the data.

// UserList.js
import { useQuery } from 'react-query';

const UserList = () => {
  const { isLoading, error, data: users } = useQuery('users', () => fetchUsers());

  // ... render users list ...
};

// UserProfile.js
import { useQuery } from 'react-query';

const UserProfile = ({ userId }) => {
  const { isLoading, error, data: users } = useQuery('users', () => fetchUsers());
  const user = users.find(user => user.id === userId);

  // ... render user profile ...
};

Both components fetch users with the same query key ('users'), resulting in a shared cache and automatic data access.

Choosing the Right Approach

The best approach depends on your specific needs. The Context API is ideal for global data sharing, while custom hooks offer more control and reusability. Shared query keys are most suitable when you need to access the same data in multiple components.

By understanding these techniques, you can effectively break down data silos and leverage React Query's caching capabilities to build more efficient and robust React applications.