https://daily.dev/blog/usequery-react-for-efficient-data-fetching
If you're diving into React and looking to manage data fetching efficiently, useQuery
from React Query is a game-changer. It simplifies data fetching, caching, and synchronization, making your app responsive and up-to-date. Here's a quick rundown:
To get started, install react-query, set up a QueryClient, and wrap your app with QueryClientProvider. Use useQuery
in your components with a unique key and a fetch function. The hook handles the rest, from loading states to caching and updating the data.
Whether you're fetching a todo list from an API or implementing a dynamic search feature, useQuery
handles the heavy lifting, letting you focus on building a great user experience. It's perfect for apps that need real-time data without the hassle of manual data management.
Understanding useQuery Hook Parameters and Return Values
Key Parameters
The useQuery
hook needs two main things to work:
For instance:
useQuery(['users', 5], async () => {
const res = await fetch('/api/users/5');
return res.json();
});
In this example, ['users', 5]
is the unique label, and the function fetches data for user ID 5.
Configuration Options
You can also tweak how useQuery
works with a few options:
Example:
useQuery('users', fetchUsers, {
cacheTime: 10000,
staleTime: 30000,
refetchOnWindowFocus: true
})
Return Values
useQuery
gives back an object with helpful info:
Example:
const { status, data, error, isFetching } = useQuery('users', fetchUsers);
if (status === 'loading') {
return <Spinner />;
}
if (status === 'error') {
return <Message error={error} />;
}
return <UserList data={data} />;
This setup lets you manage loading screens, errors, and how to show your data in a simple way.
Implementing Core Data Fetching Use Cases
Fetching Todos from API
Here's a simple way to get a list of tasks (todos) from an online service using useQuery
in your React app. This example also shows how to deal with waiting for the data to load and handling any errors that might pop up:
import { useQuery } from 'react-query';
import axios from 'axios';
function Todos() {
const fetchTodos = () => axios.get('/api/todos');
const {
isLoading,
error,
data: todos
} = useQuery('todos', fetchTodos);
if (isLoading) {
return <p>Loading...</p>;
}
if (error) {
return <p>An error occurred: {error.message}</p>;
}
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
This code neatly covers getting the data, showing a message while waiting, and dealing with errors. Once the data is fetched, it's ready to be shown.
Dynamic Search Implementation
This example shows how to set up a search feature in your React app where useQuery
automatically looks for results based on what the user types:
import { useState } from 'react';
import { useQuery } from 'react-query';
import axios from 'axios';
function Search() {
const [searchTerm, setSearchTerm] = useState('');
const {
data: results,
isLoading,
error
} = useQuery(
['search', searchTerm],
() => axios.get(`/api/search?query=${searchTerm}`),
{ enabled: !!searchTerm }
);
return (
<>
<input
type="text"
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
placeholder="Search"
/>
{isLoading && <p>Loading...</p>}
{error && <p>Something went wrong: {error.message}</p>}
<ul>
{results.map(result => (
<li key={result.id}>{result.name}</li>
))}
</ul>
</>
);
}
In this setup, the search starts only when there's something typed in. The query updates and fetches new results whenever the search term changes.
Advanced Capabilities
Caching and Background Refetching
useQuery
is really good at remembering data it has fetched before. So, if you ask for something it has already gotten, like a list of items, it won’t ask the server again but will give you the saved version. This makes your app quick for users.
But, if you always want the latest info, useQuery
offers some cool features:
You can also ask for new data whenever you want with refetch()
.
Here’s how you can set it to get new data every five minutes:
const { data } = useQuery('products', fetchProducts, {
cacheTime: 1000 * 60 * 60, // saved for 1 hour
refetchInterval: 1000 * 60 * 5, // refreshes every 5 mins
})
The cool thing is, useQuery
does all this without making your app slow or showing loading screens all the time.
Your app stays quick and keeps data up to date without users noticing much.
Implementing Paginated Data Fetching
When you need to show data in chunks, like a few items at a time, useQuery
can help. Here’s a simple way to do it:
function Results({ page }) {
const { resolvedData, latestData, status } = useQuery(
['results', page],
() => fetch(`/results?page=${page}`).then(res => res.json()),
{ keepPreviousData: true }
)
if (status === 'loading') {
return <Spinner />
}
if (status === 'error') {
return <ErrorMessage />
}
return (
<div>
{/* If new data is there, show it, otherwise show old data */}
{latestData?.results || resolvedData?.results}
<button onClick={() => setPage(page + 1)}>
Next Page
</button>
</div>
)
}
What to remember:
This makes handling pages simple without needing to juggle too much code.
Logging Query States
Another way to figure out what's going wrong is by adding logs to your queries. Here's an example:
useQuery('todos', fetchTodos, {
onError: (err) => console.log(err),
onSettled: () => console.log('Query settled'),
})
Adding these logs helps you see exactly where things are going off track, without making your code complicated.
Không có nhận xét nào:
Đăng nhận xét