React Query - The Only Guide You Need
React Query ? What is that? Let me tell you what React Query is, why should you use it? How to use the react query in the react.js application.

Search for a command to run...
React Query ? What is that? Let me tell you what React Query is, why should you use it? How to use the react query in the react.js application.

Thank you for sharing this comprehensive guide on React Query! It's great to see such a detailed breakdown of the library and how it can be used in various scenarios. As a developer who's been using React Query for some time now, I can attest to its power and efficiency. For those looking to dive even deeper into this library, I recommend to check out this React Query blog. Thanks again for the helpful insights! Website: https://www.copycat.dev/blog/react-query/
Thanks Praveen 😊. Glad that you liked it
Lessons from Code, Content, and Consistency

Reliability basics: Outbox pattern + why it matters

Introducing Kafka/Redpanda + move to event-driven workflow

Connect Orders ↔ Inventory (first working service-to-service flow)

Inventory service + gRPC + proto contracts

On this page


npm install command in the terminal before launching the application. When you execute the program after that, you'll get the following result:

npm i react-query --save
App.js file and wrap the whole Router within QueryClientProvider.
```import { QueryClientProvider } from "react-query";
function App() {
return (
<QueryClientProvider>
<Router>
....
</Router>
</QueryClientProvider>
);
}
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
function App() {
return (
<QueryClientProvider client={queryClient}>
<Router>
....
</Router>
</QueryClientProvider>
);
}
useQuery from react-query inside FruitsReactQuery.js file.import { useQuery } from "react-query";

const results = useQuery('fruits',()=>{
return axios.get('http://localhost:4000/fruits')
})
fruits as a unique key and used Axios to make a GET call, also do not forget to return the result.
result variable.const {data, isLoading} = useQuery('fruits',()=>{
return axios.get('http://localhost:4000/fruits')
})
isLoading flag.function FruitsReactQuert() {
const { data, isLoading } = useQuery("fruits", () => {
return axios.get("http://localhost:4000/fruits");
});
if (isLoading) return <div className="loading">Loading...</div>;
return (
<div className="w-full h-screen flex items-center justify-center flex-col">
{data?.data.map((fruit) => {
return <div className="text-4xl">{fruit.name}</div>;
})}
</div>
);
}
data property of it in order to obtain the fruit list.
state for data and loading in Fruits.js. But React Query, on the other hand, encapsulates all of that and makes fetching data in a react component a breeze.
function FruitsReactQuert() {
const { data, isLoading, isError, error } = useQuery("fruits", () => {
return axios.get("http://localhost:4000/abcd");
});
if (isLoading) return <div className="loading">Loading...</div>;
if (isError) return <div className="loading">Error: {error.message}</div>;
return (
<div className="w-full h-screen flex items-center justify-center flex-col">
{data?.data.map((fruit) => {
return <div className="text-4xl">{fruit.name}</div>;
})}
</div>
);
}

useEffect. However, caching is built-in to React Query.If you are unable to see, then consider throttling the network speed from the Dev tool to
Slow 3G.


db.json file and change the title.
cacheTime property by giving the milliseconds values.const { data, isLoading, isError, error } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
cacheTime: 10000, // 10 seconds
}
);
const { data, isLoading, isError, error, isFetching} = useQuery(...)

isFetching is true as react query is fetching the data. And after that, it is false as the fetching is completed.const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
staleTime: 10000,
}
);

isFetching is still false. But as soon as 10 seconds passes away and I make the request again then the isFetching value changes to true.refetchOnMount:true.

const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
refetchOnMount: true // or false, 'always'
}
);
refetchOnWindowFocustrue by default.useEffect to fetch data and the data gets changed, you will not be able to notice the change unless you refresh the entire page.Fruits React Query page and altering the title in the db.json file.
false to this parameterconst { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
refetchOnWindowFocus: true, // or false, 'always'
}
);
refetchIntervalrefetchInterval attribute to the duration in milliseconds.const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
refetchInterval: 2000, // or false
}
);

refetchIntervalInBackgroundtrue answer to refetchIntervalInBackground if you want to fetch data even if your website tab is not in focus.const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
refetchInterval: 2000,
refetchIntervalInBackground: true,
}
);

const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
onSuccess: (data) => {
console.log("Data successfully fetched: "+ data);
},
onError: (err) => {
console.log("Error occured: "+ err);
},
}
);
select useQuery option.function FruitsReactQuert() {
const { data, isLoading, isError, error, isFetching } = useQuery(
"fruits",
() => {
return axios.get("http://localhost:4000/fruits");
},
{
select: (data) => { // <--- Here
const fruitsStartsWithCharA = data?.data.filter((fruit) => {
if (fruit.name.startsWith("A")) return fruit.name;
else return null;
});
return fruitsStartsWithCharA; // <--- This will be assigned to actual `data`
},
}
);
if (isLoading) return <div className="loading">Loading...</div>;
if (isError) return <div className="loading">Error: {error.message}</div>;
return (
<div className="w-full h-screen flex items-center justify-center flex-col">
{data.map((fruit, index) => {
return <div className="text-4xl">{fruit.name}</div>;
})}
</div>
);
}
Fruits React Query Page, we have currently retrieved all of the fruits data.
function FruitDetail() {
return <div>Fruit Detail</div>;
}
export default FruitDetail;
App.jsfunction App() {
return (
<QueryClientProvider client={queryClient}>
<Router>
......
<Switch>
<Route path="/fruit-react-query/:fruitId">
<FruitDetail />
</Route>
</Switch>
</Router>
</QueryClientProvider>
);
}
Link tag of react-router-dom.<div className="w-full h-screen flex items-center justify-center flex-col">
{data?.data.map((fruit) => {
return (
<div
className="text-4xl p-4 hover:bg-blue-500 hover:text-white rounded-lg transition-all duration-150 ease-in"
key={fruit.id}
>
<Link to={`/fruit-react-query/${fruit.id}`}>{fruit.name}</Link>
</div>
);
})}
</div>

fruitIdinside the FruitDetail page. For that we will use useParams() hook from react-router-domconst { fruitId } = useParams();
const { data, isLoading, error, isError } = useQuery(
["fruit-detail", fruitId],
() => {
return axios.get(`http://localhost:4000/fruits/${fruitId}`);
}
);
fruit-detail, But this query is dependent on the fruitId as well. If you were to leave this as is fruit-detail then the cached value of fruitId 1 would be used for fruit-id 2 and 3 and so on.
const queryClient = useQueryClient();
const { data, isLoading, error, isError } = useQuery(
["fruit-detail", fruitId],
() => {
return axios.get(`http://localhost:4000/fruits/${fruitId}`);
},
{
initialData: () => {},
}
);
queryClient.getQueryData('queryUniqueKey'), you can get the cached data for a specific query.find method to locate a fruit that corresponds to fruitId and then return that fruit.const { data, isLoading, error, isError } = useQuery(
["fruit-detail", fruitId],
() => {
return axios.get(`http://localhost:4000/fruits/${fruitId}`);
},
{
initialData: () => {
const fruit = queryClient
.getQueryData("fruits")
?.data.find((fruit) => fruit.id === parseInt(fruitId));
if (fruit) {
return {
data: fruit,
};
} else {
return undefined;
}
},
}
);

<div className="w-full h-screen flex items-center justify-center flex-col">
<FruitForm />
{data?.data.map((fruit) => {
return (
<div
className="text-4xl p-4 hover:bg-blue-500 hover:text-white rounded-lg transition-all duration-150 ease-in"
key={fruit.id}
>
<Link to={`/fruit-react-query/${fruit.id}`}>{fruit.name}</Link>
</div>
);
})}
</div>

FruitForm.js
function FruitForm() {
const [fruitName, setFruitName] = useState("");
const [fruitDescription, setFruitDescription] = useState("");
const handleAddFruit = () => {};
return (
<section class="max-w-4xl p-6 mx-auto bg-white rounded-md shadow-md dark:bg-gray-800">
<form>
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2">
<div>
<label class="text-gray-700 dark:text-gray-200" for="username">
Fruit Name
</label>
<input
id="fruitName"
type="text"
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
onChange={(e) => setFruitName(e.target.value)}
value={fruitName}
/>
</div>
<div>
<label class="text-gray-700 dark:text-gray-200" for="emailAddress">
Fruit Description
</label>
<input
id="description"
type="text"
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border border-gray-300 rounded-md dark:bg-gray-800 dark:text-gray-300 dark:border-gray-600 focus:border-blue-500 dark:focus:border-blue-500 focus:outline-none focus:ring"
onChange={(e) => setFruitDescription(e.target.value)}
value={fruitDescription}
/>
</div>
</div>
<div class="flex justify-end mt-6">
<button
onClick={handleAddFruit}
class="px-6 py-2 leading-5 text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600"
>
Add
</button>
</div>
</form>
</section>
);
}
useMutation hookimport { useMutation } from "react-query";
useMutation hook doesn't need a unique key. So the first argument of this hook is a function that will post data to the back-end.function FruitForm() {
const [fruitName, setFruitName] = useState("");
const [fruitDescription, setFruitDescription] = useState("");
const addFruit = (fruit) => {
return axios.post("http://localhost:4000/fruits", fruit);
};
const { mutate } = useMutation(addFruit);
const handleAddFruit = (e) => {
e.preventDefault();
mutate({
name: fruitName,
description: fruitDescription,
});
setFruitName("");
setFruitDescription("");
};
return (...)
}
useMutation hook we passed a function called addFruit.useQuery, useMutation returns some value that we can destructure. In our case, we need mutate. This is a function that we need to call to make a POST request. mutate function and passed the object that contains fruit information.
db.json will be updated.
mutations. We call the use mutation hook passing in a mutation function. . When you click the Add button, the fruit name and description are recorded in db.json. Everything is in working order.fruits query as soon as the mutation succeeds?import { useQueryClient } from 'react-query';
const queryClient = useQueryClient()
const { mutate } = useMutation(addFruit,{
onSuccess: () => {}
});
const { mutate } = useMutation(addFruit,{
onSuccess: () => {
queryClient.invalidateQueries('fruits')
}
});
fruits query. That's pretty much it. Now we can test it.
ReactQueryDevtoolsimport { ReactQueryDevtools } from 'react-query/devtools'
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* The rest of your application */}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}

