Using Context API with React Query (Tanstack Query) — React Native

Krishan Madushanka
5 min readMar 9, 2024

--

Using Context API with React Query (Tanstack Query) — React Native

Handling REST API calls is a very common thing in web and mobile applications which uses server — client architecture. State management is also a prominent topic discussed in both hybrid mobile application development and web development. In mobile app development with react native Redux and Context API is frequently used for state management. Let’s discuss how we can use context api in combination with React Query in this article. React Query is a library that makes our lives easier when used with rest api calls and let’s look at how, in a second.

Context API

Context API is a (kind of) new feature added in version 16.3 of React that allows one to share state across the entire app (or part of it) lightly and with ease.

React Query

React Query is often described as the missing data-fetching library for React, but in more technical terms, it makes fetching, caching, synchronizing and updating server state in your React applications a breeze. — official documentation

Setup React Query

First setup a react native project and create a src directory in the folder structure.Install React Query using following command.

npm i react-query

Next create a file called src/useGetComments.js and add following code.

import {useQuery} from 'react-query';

const getComments = async () => {
const url = 'https://jsonplaceholder.typicode.com/comments/1';

try {
const response = await fetch(url);

if (!response.ok) {
throw new Error('Network response was not ok');
}

const data = await response.json();
console.log('Parsed JSON data:', data);

return data;
} catch (error) {
console.error('Fetch error:', error);
return null;
}
};

export function useGetComments() {
return useQuery(['getComments'], () => getComments());
}

This file is the place where we add the code for making the api call. Inside getComments function I have added the code for making the api call using fetch method which ships with javascript itself. Below that, inside useGetComments function getComments function is passed as the second parameter to the useQuery function. As the first parameter we have to pass an unique key for the query. I have passed [‘getComments’] for that.

useQuery is used for making GET requests. If you want to do a request with pagination you will use useInfiniteQuery. For other request types like POST, PUT, PATCH etc, we can use useMutation function from react query. You can refer the official documentation to learn how to use different type of queries.

Now setup the queryClient with QueryClientProvider in App.js as follows,

import React from 'react';
import {QueryClient, QueryClientProvider} from 'react-query';

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
// UI components goes here...
</QueryClientProvider>
);
}

export default App;

Setup Context API

Create a file named src/commentsContext.js and add following code.

import React, {createContext, useMemo} from 'react';
import {useGetComments} from './useGetComments';

export const CommentsContext = createContext(null);

export const CommentsProvider = ({children}) => {
const {data, isFetching, refetch} = useGetComments();

const commentsContext = useMemo(
() => ({data, isFetching, refetch}),
[data, isFetching, refetch],
);

return (
<CommentsContext.Provider value={commentsContext}>
{children}
</CommentsContext.Provider>
);
};

Here, context is created using createContext function provided by react. Then we create the provider for this context.This provider is used to provide our cintext to the UI components in this application. children parameter here is the that we are going to wrap with this provider. Inside CommentsProvider function we use the service function that we created earlier. It will return data and some other functions returned by useQuery function. Using object destruturing we can get the returned values in to variables.

data — data returned from the api call.
isFetching — a boolean value which is true when async rest api call is in work and returns false when async call is finished. We can easily use this for showing a loader when data is fetching.
refetch — function to call when we want to recall the api function.

These are only few values that returned by react query functions and there are many that you can use depending on your requirement. But note that these functions are provided by react query that makes our lives easier.

When any parameter inside dependency array of useMemo function ( [data, isFetching, refetch] ) changes, Context API will update the UI accordingly. Finally in this file we return our context provider with the values of context. values will be the commentsContext here consists of data, isFetching and refetch. These values will be provided to our UI using the context provider.

Using the Context in the UI

Create file called src/comments.js and add following code.

import {
ActivityIndicator,
Text,
TouchableOpacity,
View,
StyleSheet,
} from 'react-native';
import {useComments} from './useComments';

export const Comments = () => {
const {data, isFetching, refetch} = useComments();

const onPress = () => {
refetch();
};

return (
<View style={styles.container}>
{isFetching ? (
<ActivityIndicator color={'red'} />
) : (
<View style={styles.bottomContainer}>
<Text style={styles.text}>{data?.body}</Text>
<TouchableOpacity onPress={onPress} style={{marginTop: 20}}>
<Text>Press</Text>
</TouchableOpacity>
</View>
)}
</View>
);
};

const styles = StyleSheet.create({
container: {alignItems: 'center', justifyContent: 'center', flex: 1},
bottomContainer: {alignItems: 'center'},
text: {color: 'red', marginTop: 100, paddingHorizontal: 20},
});

To read the context we must use useContext hook from react. To setup that we’ll use a separate file called src/useComments.js.

import * as React from 'react';
import {CommentsContext} from './commentsContext';

export const useComments = () => {
const context = React.useContext(CommentsContext);
if (!context) {
throw new Error('CommentsContext must be within CommentsContextProvider');
}

return context;
};

This hook is called inside comments.js file. Now let’s provide our context to the Comments component.In App.js,

import React from 'react';
import {QueryClient, QueryClientProvider} from 'react-query';
import {Comments} from './src/comments';
import {CommentsProvider} from './src/commentsContext';

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
<CommentsProvider>
<Comments />
</CommentsProvider>
</QueryClientProvider>
);
}

export default App;

Here we have wrapped Comments component with our context provider and inside comments component we can read the context data returned by the comments context.

Observe how I have used isFetching to show the loader and refetch to fetch the data again when we press on a button.

React Query includes a robust caching mechanism that helps in storing and retrieving data efficiently. Cached data can be easily invalidated or refreshed based on various conditions.

Final output

Find the full codebase from here.
Hit on clap, share and comment to motivate me :)

--

--

Krishan Madushanka

Software Engineer | Android | iOS | Flutter | React Native | IoT | aws certified