Fetching data with react-query
📡 What you will learn
- Fetch data over the network from the Star Wars API.
- Display status and datas with
useQuery
. - Use an advanced React Pattern: Context API.
- Build your own custom hook.
👾 Before we start the exercise
- You should have a look at the SWAPI documentation
While many developers underestimate the complexity associated with asynchronous calls, they are a very large and complex problem (handling load state, error state, cache, refetch).
A simple, high-performance integration can be very tricky.
We are going to use TanStack Query
, here is a video explaining why.
React Query is presented as a library of hooks for loading, caching, and modifying asynchronous data in React. It offers many features: a simple query with error and load status, dependent or parallel queries, and paged queries. It also includes simple and efficient cache management and ensures compatibility with server-side rendering, notably Next.js.
Here's how it works:
- Write your data fetching functions (here it's
getDataFromApi
). - Wrap them in a named query with
queryKey
as an array ofstring
(here it's["dataFromApi"]
). react-query
handles caching, deduping, re-fetching, and loading states.
// DO NOT MONKEY COPY/PASTE ME
async function getDataFromApi() {
const result = await fetch(`https://api.example.com/collection/`);
const json = await result.json();
return json;
}
function Component({ itemId }) {
const { isLoading, isError, data } = useQuery(
["dataFromApi"],
getDataFromApi
);
if (isLoading) {
return <Text>Loading…</Text>;
}
if (isError) {
return <Text>Something bad happened…</Text>;
}
return <DoStuffWithData data={data} />;
}
👨🚀 Exercise 2
That's the screen we will create: a list of data

Setup react-query
- Install the library
npm install @tanstack/react-query
- Add a
QueryClientProvider
and wrap the application entry point.
🔭 Hint: You can have a look at the QueryClientProvider
documentation
Fetching resources across the network
- Take 5 min to read carefully the
useQuery
documentation.
In the example useQuery
, isLoading
and isError
lives on the same files.
To have a more robust application, and separte the concerns of the data and the ui, we can wrap our queries into one custom hook useStarships()
.
The logic is:
fetch
data from the endpoint and return the result as ajson
- Get the result from the fetch and return the result of
useQuery
- Use our custom hook to render the UI
- Create a new file
useStarships.ts
and paste the content bellow
// ./src/hooks/useStarships.ts
import { useQuery } from "@tanstack/react-query";
async function fetchData() {
const result = await fetch(`https://swapi.py4e.com/api/starships/`);
const json = await result.json();
return json;
}
export function useStarships() {
return useQuery(["starships"], fetchData);
}
Now you can write useStarships()
anywhere in your Screen and React Query handles the rest.
- Go to your Feed screen and remplace the
data.json
with data from the swapi. - Use
useStarships
hook to dislay a loading message. - Use
useStarships
hook to handle errors. - Use
useStarships
hook to render data with aFlatList
.
If you want to display some images on your Card
, you can use this placeholder https://picsum.photos/400/200
as a source
.
👽 Bonus
- Save this talk to your "Watch later" playlist: Custom Hooks in React: The Ultimate UI Abstraction Layer from Tanner Linsley
- Display a nice animated placeholder during loading with rn-placeholder
- Add a "Pull to Refresh" functionality to your FlatList with
onRefresh