React Query State Management
Tags: react, webdev, tutorial
Published: 2024-04-08 08:21:51

### What is React Query?
React Query is a library that provides a simple and intuitive solution for asynchronous data management and caching in React applications. The REST API provides a declarative API for retrieving, caching, synchronizing, and updating data from various sources, such as GraphQL endpoints or even local storage. With React Query, developers can remove the complexity of managing asynchronous state and focus more on building the user interface.

### Key concepts:

1. **Queries**: Reaction Request on Request represents an asynchronous data retrieval operation. It contains logic to transparently handle errors and successful conditions for retrieving and loading data from certain sources.

2. **Query Key** : Key claims are unique identifiers for claims that identify and authenticate a client. Depending on how the data is captured, it can be a simple string or a complex object.

3. **Query Function**: Request function is an asynchronous function responsible for receiving data. Instances are passed as arguments to find and return data from resources.

4. **Mutation**: Mutation allows you to perform synchronous or asynchronous state updates and reversals. They provide an easy way to interact with server-side APIs for CRUD (Create, Read, Update, Destroy) operations.

5. **Query Invalidation**: React Query automatically invalidates caches based on configurable rules, such as time-to-live (TTL), manual invalidation, or resets on certain events. This ensures that the cached data is up-to-date and consistent with the server.

#### Installation :

To get started with React Query, you need to install in your project:

```head
npm install reaction-query
```

Once installed, you can use React Query by wrapping your application with 
"<QueryClientProvider>" and instantiating a "QueryClient" instance.

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

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* Your application components */}
    </QueryClientProvider>
  );
}

export default App;

```

### Fetching Data:

```jsx
import React from 'react';
import { useQuery } from 'react-query';

const fetchUsers = async () => {
  const response = await fetch('/api/users');
  if (!response.ok) {
    throw new Error('Failed to fetch users');
  }
  return response.json();
};

function UserList() {
  const { data, isLoading, isError } = useQuery('users', fetchUsers);

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error fetching data</div>;

  return (
    <ul>
      {data.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

export default UserList;
```

## Mutation:
React Query makes it easy to update state and mutate data using the "useMutation" hook. Let's see an example of updating user data.

```jsx
import React from 'react';
import { useMutation, useQueryClient } from 'react-query';

const updateUser = async (id, newData) => {
  const response = await fetch(`/api/users/${id}`, {
    method: 'PUT',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(newData),
  });

  if (!response.ok) {
    throw new Error('Failed to update user');
  }

  return response.json();
};

function UserForm({ user }) {
  const queryClient = useQueryClient();
  const updateUserMutation = useMutation(updatedData => updateUser(user.id, updatedData), {
    onSuccess: () => {
      queryClient.invalidateQueries('users');
    },
  });

  const handleSubmit = event => {
    event.preventDefault();
    const formData = new FormData(event.currentTarget);
    const updatedData = Object.fromEntries(formData.entries());
    updateUserMutation.mutate(updatedData);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" defaultValue={user.name} />
      <button type="submit">Update</button>
    </form>
  );
}

export default UserForm;
```