Menggunakan `useQuery` dan `useMutation

Sekarang mari kita bahas lebih dalam tentang penggunaan `useQuery` dan `useMutation` di React Query. Keduanya merupakan hook yang sangat powerful untuk menangani pengambilan data dan mutasi data di aplikasi React.

### 1. **useQuery** – Pengambilan Data

`useQuery` adalah hook utama yang digunakan untuk mengambil data dari API secara efisien. Hook ini mendukung caching, re-fetching otomatis, pagination, dan bahkan handling error dengan mudah.

#### Sintaks Dasar `useQuery`

```javascript
const { data, error, isLoading, isError } = useQuery(queryKey, queryFn, options);

- `queryKey`: Unik untuk setiap request. React Query menggunakan ini untuk meng-cache dan mengidentifikasi query.
- `queryFn`: Fungsi yang digunakan untuk mengambil data, seperti fetch atau axios call.
- `options`: Berbagai konfigurasi tambahan untuk caching, polling, retry, dsb.

#### Contoh Penggunaan `useQuery`

Mari kita implementasikan contoh sederhana dari `useQuery` untuk mengambil data dari API.

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

const fetchTodos = async () => {
  const response = await axios.get('https://jsonplaceholder.typicode.com/todos');
  return response.data;
};

function Todos() {
  const { data, error, isLoading, isError } = useQuery('todos', fetchTodos);

  if (isLoading) return <div>Loading...</div>;
  if (isError) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>Todo List</h1>
      <ul>
        {data.map(todo => (
          <li key={todo.id}>{todo.title}</li>
        ))}
      </ul>
    </div>
  );
}

#### Beberapa Opsi Konfigurasi `useQuery`

- **`staleTime`**: Menentukan berapa lama data dianggap "fresh" sebelum React Query memutuskan untuk re-fetch data. Jika data masih dalam status "fresh", data dari cache akan digunakan.
 
  ```javascript
  const { data } = useQuery('todos', fetchTodos, { staleTime: 10000 }); // Data fresh selama 10 detik
  ```

- **`cacheTime`**: Menentukan berapa lama data akan disimpan dalam cache setelah tidak digunakan lagi (misal, user berpindah halaman).

  ```javascript
  const { data } = useQuery('todos', fetchTodos, { cacheTime: 60000 }); // Cache data selama 1 menit
  ```

- **`refetchOnWindowFocus`**: Mengatur apakah React Query akan melakukan re-fetch data ketika user kembali ke tab browser.

  ```javascript
  const { data } = useQuery('todos', fetchTodos, { refetchOnWindowFocus: false });
  ```

- **`enabled`**: Jika `false`, query tidak akan berjalan otomatis dan hanya bisa di-trigger secara manual.

  ```javascript
  const { data } = useQuery('todos', fetchTodos, { enabled: false });
  ```

#### Refetch Data

Kamu bisa secara manual memicu re-fetch data dengan memanfaatkan `refetch` dari `useQuery`.

```javascript
const { data, refetch } = useQuery('todos', fetchTodos);

return (
  <div>
    <h1>Todo List</h1>
    <button onClick={() => refetch()}>Refetch Data</button>
    <ul>
      {data.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  </div>
);

### 2. **useMutation** – Mutasi Data (POST, PUT, DELETE)

`useMutation` digunakan untuk mengelola operasi perubahan data seperti POST, PUT, DELETE. Dengan `useMutation`, kita bisa melakukan operasi yang mengubah data dan secara otomatis memperbarui cache.

#### Sintaks Dasar `useMutation`

```javascript
const mutation = useMutation(mutationFn, options);

- `mutationFn`: Fungsi yang digunakan untuk melakukan mutasi (misalnya, POST atau PUT request).
- `options`: Opsi tambahan seperti callback untuk handling success atau error, dan melakukan optimistic updates.

#### Contoh Penggunaan `useMutation`

Di bawah ini adalah contoh bagaimana kita bisa menggunakan `useMutation` untuk menambahkan user baru ke dalam daftar.

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

const addUser = async (newUser) => {
  const response = await axios.post('https://jsonplaceholder.typicode.com/users', newUser);
  return response.data;
};

function AddUser() {
  const queryClient = useQueryClient();

  const mutation = useMutation(addUser, {
    onSuccess: () => {
      // After mutation succeeds, invalidate the users query to fetch the updated data
      queryClient.invalidateQueries('users');
    },
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    const name = e.target.elements.name.value;
    mutation.mutate({ name });
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" name="name" placeholder="Enter user name" />
      <button type="submit">Add User</button>
      {mutation.isLoading && <p>Adding user...</p>}
      {mutation.isError && <p>Error: {mutation.error.message}</p>}
    </form>
  );
}

#### Beberapa Opsi Konfigurasi `useMutation`

- **`onSuccess`**: Callback yang dijalankan setelah mutation berhasil. Ini sering digunakan untuk invalidating query agar data yang di-fetch bisa diperbarui.
 
  ```javascript
  useMutation(addUser, {
    onSuccess: () => {
      queryClient.invalidateQueries('users');
    },
  });

- **`onError`**: Callback yang dijalankan jika mutation gagal. Ini bisa digunakan untuk menampilkan pesan error atau rollback perubahan.

  ```javascript
  useMutation(addUser, {
    onError: (error) => {
      console.log(error.message);
    },
  });

- **`onMutate`**: Callback yang dijalankan sebelum mutation. Ini sering digunakan untuk **optimistic updates**, di mana kita mengupdate UI seolah-olah request sudah berhasil, lalu melakukan rollback jika gagal.

  ```javascript
  useMutation(addUser, {
    onMutate: (newUser) => {
      queryClient.setQueryData('users', (oldData) => [...oldData, newUser]);
    },
    onError: (err, newUser, context) => {
      queryClient.setQueryData('users', context.previousData); // Rollback jika error
    },
  });

### Optimistic Updates dengan `useMutation`

Optimistic updates memungkinkan aplikasi untuk merespons segera tanpa menunggu server merespons. Ini memberikan pengalaman yang lebih responsif kepada pengguna. Namun, jika mutation gagal, kita harus rollback perubahan.

```jsx
const mutation = useMutation(addUser, {
  onMutate: async (newUser) => {
    await queryClient.cancelQueries('users'); // Membatalkan query yang sedang berjalan

    const previousUsers = queryClient.getQueryData('users');
    queryClient.setQueryData('users', (old) => [...old, newUser]); // Optimistic update

    return { previousUsers }; // Mengembalikan data lama jika perlu rollback
  },
  onError: (err, newUser, context) => {
    queryClient.setQueryData('users', context.previousUsers); // Rollback
  },
  onSettled: () => {
    queryClient.invalidateQueries('users'); // Refetch data terbaru setelah mutation
  },
});

### Kesimpulan
- **`useQuery`** digunakan untuk pengambilan data dengan dukungan caching, re-fetching, dan handling error yang efisien.
- **`useMutation`** digunakan untuk operasi yang mengubah data (POST, PUT, DELETE), dengan dukungan handling success/error, dan optimisasi melalui **optimistic updates**.
- React Query mempermudah pengelolaan data server dengan API sederhana dan kaya fitur, meminimalkan boilerplate yang harus ditulis secara manual.

Posting Komentar

Lebih baru Lebih lama

Formulir Kontak