React Native has become one of the most popular frameworks for building cross-platform mobile applications. However, managing server state, caching, and data synchronization can be challenging. This is where TanStack Query (formerly known as React Query) comes into play. TanStack Query is a powerful library that simplifies data fetching, caching, and state management in React applications. In this guide, we’ll explore how to integrate TanStack Query with React Native to build efficient and scalable mobile apps.
Why Use TanStack Query with React Native?
TanStack Query provides several benefits for React Native developers:
- Simplified Data Fetching: TanStack Query abstracts away the complexities of managing asynchronous data fetching, reducing boilerplate code.
- Automatic Caching: It automatically caches data and intelligently manages cache invalidation, ensuring your app remains performant.
- Background Refetching: TanStack Query can refetch data in the background to keep your UI up-to-date.
- Optimistic Updates: It supports optimistic updates, allowing you to update the UI before the server responds.
- Error Handling: Built-in error handling and retry mechanisms make it easier to manage failed requests.
Setting Up TanStack Query in React Native
Before diving into the integration, ensure you have a React Native project set up. If you don’t have one, create a new project using the following command:
npx create-expo-app@latest TanStackAppDemo
Step 1: Install TanStack Query
To use TanStack Query in your React Native project, install the required package:
npm install @tanstack/react-query
Step 2: Set Up the QueryClient
The QueryClient is the core of TanStack Query. It manages the caching and state of your queries. Wrap your application with the QueryClientProvider and pass an instance of QueryClient to it.
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import HomeScreen from './screens/HomeScreen';
const queryClient = new QueryClient();
const App = () => {
return (
<QueryClientProvider client={queryClient}>
<HomeScreen />
</QueryClientProvider>
);
};
export default App;
Fetching Data with TanStack Query
Now that TanStack Query is set up, let’s fetch data in a React Native component. We’ll use the useQuery hook to fetch and display a list of items.
Example: Fetching and Displaying Data
import React from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import { useQuery } from '@tanstack/react-query';
const fetchPosts = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};
const HomeScreen = () => {
const { data, isLoading, isError, error } = useQuery({
queryKey: ['posts'], // Unique key for the query
queryFn: fetchPosts, // Function to fetch data
});
if (isLoading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}
if (isError) {
return <Text className="text-red-500">Error: {error.message}</Text>;
}
return (
<View className="flex-1 p-4 bg-white">
<FlatList
data={data}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => (
<View className="mb-4 p-4 bg-gray-50 rounded-lg">
<Text className="text-lg font-bold">{item.title}</Text>
<Text className="text-gray-700">{item.body}</Text>
</View>
)}
/>
</View>
);
};
export default HomeScreen;
Mutating Data with TanStack Query
In addition to fetching data, TanStack Query provides the useMutation hook for performing create, update, and delete operations.
Example: Adding a New Post
import React, { useState } from 'react';
import { View, TextInput, Button, Alert } from 'react-native';
import { useMutation, useQueryClient } from '@tanstack/react-query';
const AddPostScreen = () => {
const [title, setTitle] = useState('');
const [body, setBody] = useState('');
const queryClient = useQueryClient();
const addPost = async (newPost) => {
const response = await fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newPost),
});
if (!response.ok) {
throw new Error('Failed to add post');
}
return response.json();
};
const mutation = useMutation({
mutationFn: addPost,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
Alert.alert('Success', 'Post added successfully!');
setTitle('');
setBody('');
},
onError: (error) => {
Alert.alert('Error', error.message);
},
});
const handleSubmit = () => {
mutation.mutate({ title, body });
};
return (
<View className="flex-1 p-4 bg-white">
<TextInput
className="mb-4 p-2 border border-gray-300 rounded"
placeholder="Title"
value={title}
onChangeText={setTitle}
/>
<TextInput
className="mb-4 p-2 border border-gray-300 rounded"
placeholder="Body"
value={body}
onChangeText={setBody}
multiline
/>
<Button title="Add Post" onPress={handleSubmit} />
</View>
);
};
export default AddPostScreen;
Optimizing Performance
TanStack Query provides several features to optimize performance in React Native apps:
- Stale Time: Configure how long data remains fresh before refetching.
- Cache Time: Control how long data stays in the cache.
- Pagination and Infinite Queries: Use useInfiniteQuery for paginated data.
- Prefetching: Prefetch data to improve user experience.
Conclusion
Integrating TanStack Query with React Native simplifies data management, improves performance, and enhances the developer experience. By leveraging its powerful features like caching, background refetching, and optimistic updates, you can build robust and scalable mobile applications. Start integrating TanStack Query into your React Native projects today and experience the difference! Let me know if you need further assistance or additional examples! 🏝️