In this article, I will be going through the basics of React Query and how it can be used to build a simple user list application. as per React Query site

React Query is a Performant and powerful data synchronization for React to Fetch, cache and update data in your React and React Native applications all without touching any “global state”.

Contents

Project Setup

npx create-react-app react-query-handson
cd react-query-handson
yarn add axios react-query
yarn start

open project in your preferred text editor.

Configure React Query

to make use of react query, we have to wrap our main app component inside QueryClientProvider component. Then we need to provide client by initializing QueryClient as follows,

import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

ReactDOM.render(
  // wrap the app in the query client provider
  <QueryClientProvider client={queryClient}>
    <App />
  </QueryClientProvider>,
  document.getElementById("root")
);

index.js file will look like below snippet.

import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { QueryClient, QueryClientProvider } from "react-query";
// create a query client
const queryClient = new QueryClient();
ReactDOM.render(
// wrap the app in the query client provider
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
document.getElementById("root")
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
view raw index.js hosted with ❤ by GitHub

after configuring the provider, we need to implement data fetching and uploading logic in our components. The hooks are as follows,

  • useQuery
  • useMutation

useQuery

  • useQuery is a hook which returns the data from the server.
  • useQuery syntax is as follows,
useQuery({
  queryKey, // key used to identify the query in the cache
  queryFn, // function which returns the query object
  enabled, // boolean to enable or disable the query, default: true
  retry, // number of retries in case of error, number
});

useMutation

  • useMutation takes two arguments, first is the query name and second is the options params.
  • useMutation syntax is as follows,
useMutation(mutationFn, {
  retry, // number of retries in case of error, default: boolean | number
  onSuccess // callback function to be called on success
  onError // callback function to be called on error
});

Hooks usage

to make use of the useQuery and useMutation hook, create components folder and create User.js and Users.js files.

import React from "react";
import { useQuery } from "react-query";
import axios from "axios";
import User from "./User";
export default function Users() {
const fetchUsers = async () => {
const response = await axios.get(
`https://gorest.co.in/public/v1/users?page=66`
);
return response.data;
};
const { data, isLoading, error, isError } = useQuery("users", fetchUsers, {
refetchOnWindowFocus: false,
});
if (isLoading) return <p>Loading…</p>;
if (isError) return <p>Error {error.message}</p>;
return (
<div className="container">
<User />
<h1>Users</h1>
<table>
<tbody>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Status</th>
</tr>
{data?.data?.map((user) => {
return (
<tr key={user.id}>
<td>{user.id} </td>
<td>{user.name} </td>
<td>{user.email} </td>
<td>{user.status} </td>
</tr>
);
})}
</tbody>
</table>
</div>
);
}
view raw Users.js hosted with ❤ by GitHub
// Users.js
import { useQuery } from "react-query";

const { data, isLoading, error, isError } = useQuery("users", fetchUsers, {
  refetchOnWindowFocus: false, // this is optional, if this option enabled, then the data will be refetched on window focus
});

the above code will return the data from the server and the loading state.

import React, { useState } from "react";
import { useMutation, useQueryClient } from "react-query";
import axios from "axios";
const gender = ["male", "female"];
const status = ["active", "inactive"];
const random = (array) => array[Math.floor(Math.random() * array.length)];
export default function User() {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const queryClient = useQueryClient();
const createUser = async (input) => {
Object.assign(input, { gender: random(gender), status: random(status) });
const response = await axios.post(
"https://gorest.co.in/public/v1/users",
input,
{
headers: {
Authorization: `Bearer ${process.env.REACT_APP_ACCESS_TOKEN}`,
},
}
);
setMessage(response.data);
};
const { isLoading, error, isError, mutate } = useMutation(createUser, {
onSuccess: async () => queryClient.invalidateQueries("users"),
});
return (
<>
<h1>Create a new user</h1>
<form className="user" onSubmit={(e) => e.preventDefault()}>
<div className="input">
<label>Name:</label>
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
required
/>
</div>
<div className="input">
<label>Email:</label>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<br />
<div className="input">
<button onClick={() => mutate({ name, email })}>Create</button>
</div>
</form>
<p> Created a new User : {message && JSON.stringify(message?.data)}</p>
<div style={{ color: isError ? "red" : "green" }}>
{isLoading ? "saving.." : ""}
{isError ? error.message : ""}
</div>
</>
);
}
view raw User.js hosted with ❤ by GitHub
// User.js
import { useMutation, useQueryClient } from "react-query";

const queryClient = useQueryClient();

const { isLoading, error, isError, mutate } = useMutation(createUser, {
  onSuccess: async () => queryClient.invalidateQueries("users"),
});

the above code lines are used to create a useMutation hook which returns the mutate function which can be used to make the mutation request.

the onSuccess method is used to refetch the data from server after a post request to server is successful.

now open the network inspector in your browser and check the network requests. you can see the get request for fetching the users data will be fired after every successful post request. this is because the onSuccess method is used to invalidate the users cache.

From the above example we don’t have to use useEffect and useState hook to fetch the updated data from server, we can do it by invalidating the cache.

check the github repo for the source code.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.