Meningkatkan User Experiece (UX) Aplikasi Menggunakan useOptimistic Hooks pada React JS/Next JS
Tags: react, nextjs, javascript
Published: 2024-06-02 14:53:10


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cxyzkdebg61icmdiymdy.png)

Seberapa penting emang _user experience_ (UX) dari user terhadap aplikasi yang kita kembangkan? Sangat penting bro. Kalau _first impression_ dari user terhadap aplikasi kita sudah jelek gara-gara _user experience_ yang tidak ramah lingkungan, maka user pun juga males buat buka aplikasi yang kita kembangkan. Emang ada parameternya buat nentuin bahwa UX aplikasi kita udah ramah lingkungan? Ada, parameter yang paling minimal itu penggunaan _loading _ ketika melakukan pemrosesan data/perubahan state.

Pada React JS kita bisa meningkatkan UX dari aplikasi yang kita kembangkan menggunakan useOptimistic Hooks yang bisa temen-temen baca dokumentasinya [disini ](https://react.dev/reference/react/useOptimistic) sebelum masuk lebih dalam dan implementasinya. Perlu diketahui ya temen-temen useOptimistic ini hanya tersedia pada React Canary dan Experimental Channel. Tapi, bukan berarti temen-temen kalau tidak menggunakan React Canary tidak mau berkenalan dengan useOptimistic Hooks. Tidak ada salahnya mencari ilmu baru.

Kira-kira dari 2 perbandingan di bawah ini, temen-temen lebih prefer memilih yang mana?

GIF 1. Tanpa menggunakan useOptimistic Hooks:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tivuge1srjf2gzi7fbtm.gif)

GIF 2. Menggunakan useOptimistic Hooks:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aamhxnqohgh431hqqd9z.gif)

Terdapat perbedaan yang cukup signifikan dari implementasi _useOptimistic_ Hooks pada komponen React JS/Next JS. Gif 1 tidak memberi tahu bahwa ada proses yang sedang terjadi ke _backend_ ketika menambahkan data baru, sedangkan Gif 2 memberi tahu kepada user dengan menambahkan opacity ketika ada proses pengiriman data ke _backend_. Saya pribadi lebih memilih opsi yang kedua karena ketika kita membuat sebuah aplikasi pastinya kita ingin user dapat berinteraksi dengan aplikasi kita sehingga _user experience_ dapat terbentuk hanya dengan hal yang cukup sederhana seperti ini.

Oke, kita lanjut ke tahap implementasi kode. Kali ini saya menggunakan Next JS untuk implementasi _useOptimistic Hooks_ ini. Disini temen-temen juga bisa praktik dengan menjalankan kode program yang sudah saya buat ya.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q71b6xm85k2zqysbse8u.png)

```javascript
"use client"

import { useState } from "react";
import { Todo } from "./Todo";

async function deliverTodos(todo: string) {
  await new Promise((res) => setTimeout(res, 1000));
  return todo;
}

export default function Home() {
  const [todos, setTodos] = useState([
    { text: "Mengerjakan Tugas", sending: false }
  ]);
  async function sendTodos(formData: any) {
    const sentTodo = await deliverTodos(formData.get("todo"));
    setTodos((todos: any) => [...todos, { text: sentTodo }]);
  }
  return (
    <main className="h-screen w-screen flex items-center justify-center">
      <div className="flex flex-col">
        <Todo todos={todos} sendTodos={sendTodos} />
      </div>
    </main>
  );
}
```

Lanjut, kita akan coba breakdown terlebih dahulu kode program yang sudah saya buat.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pf84fs2rf0nx862j296d.png)

_Function deliverTodos_ ini kita analogikan sebagai function yang digunakan untuk melakukan request ke backend dengan durasi request dan response 1 detik. Jadi, kalau temen-temen udah punya endpoint sendiri bisa diimplementasikan pada function ini.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwn1yccj7up8dh5j0jow.png)

Kita membutuhkan 1 state yaitu todos sebagai initiator value dan digunakan untuk menyimpan perubahan value yang akan kita gunakan pada useOptimistic Hooks.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0b3a938dvequy2z6c9zg.png)

```javascript
/* eslint-disable react/jsx-key */
"use client";
import { useOptimistic, useRef } from "react";

export function Todo({ todos, sendTodos }: any) {
    const formRef = useRef<HTMLFormElement>(null);

    async function formAction(formData: FormData) {
        addOptimisticTodo(formData.get("todo"));
        formRef.current?.reset();
        await sendTodos(formData); // proses penambahan data ke database secara async
    }

    const [optimisticTodo, addOptimisticTodo] = useOptimistic(
        todos,
        (state, newTodo) => [
            ...state,
            {
                text: newTodo,
                sending: true
            }
        ]
    );

    return (
        <>
            <h1 className="text-black">Todo List Application</h1>
            <div className="flex flex-col space-y-2 my-2">
                {optimisticTodo.map((todo: any, index: number) => (
                    <div className="w-full">
                        <div
                            className={`bg-gray-100 
                        rounded flex p-4 h-full 
                        items-center text-black 
                        ${!!todo.sending ? 'opacity-20' : ''}`}>
                            <svg
                                fill="none"
                                stroke="currentColor"
                                stroke-linecap="round"
                                stroke-linejoin="round"
                                stroke-width="3"
                                className="text-indigo-500 w-6 h-6 flex-shrink-0 mr-4"
                                viewBox="0 0 24 24">
                                <path d="M22 11.08V12a10 10 0 11-5.93-9.14"></path>
                                <path d="M22 4L12 14.01l-3-3"></path>
                            </svg>
                            <span className="font-medium">{todo.text}</span>
                        </div>
                    </div>
                ))}
            </div>
            <form action={formAction} ref={formRef} className="flex flex-col">
                <input type="text"
                    className="bg-gray-50 border 
                border-gray-300 text-gray-900 text-sm rounded-lg 
                focus:ring-blue-500 focus:border-blue-500 block 
                w-full p-2.5 dark:bg-gray-200 dark:border-gray-200 
                dark:placeholder-gray-400 dark:text-black 
                dark:focus:ring-red-500 dark:focus:border-blue-500 
                my-5"
                    name="todo"
                    placeholder="Add Todo Today"
                    autoComplete="off" />
                <button
                    type="submit"
                    className="
                text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 
                focus:outline-none focus:ring-blue-300 
                font-medium rounded-lg text-sm w-full 
                sm:w-auto px-5 py-2.5 text-center 
                dark:bg-blue-600 dark:hover:bg-blue-700 
                dark:focus:ring-blue-800">Add</button>
            </form>
        </>
    );
}
```

Kita akan breakdown lagi kode program yang ada pada <Todo /> component.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yzscu5vz13av7vd00qii.png)

_**function formAction**_ merupakan function yang digunakan untuk menambahkan hasil input todo ke dalam _**addOptimisticTodo**_ yang mana function ini merupakan function yang akan kita definisikan pada _useOptimisitic destruct_. Lalu, kita bisa mengirim data ke API secara asynchronous.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/znfayqnlewnp7zh15thy.png)

Lalu kita bisa mendefinisikan _passthrough_ dan _reducer_ yang ada pada _useOptimistic Hooks_. Disini saya definisikan passthrough dengan nama _optimisticTodo_ dan _reducer_ sebagai _addOptimisticTodo_. Kemudian, didalam parameter _useOptimistic_ kita bisa kirimkan todos sebagai _passthrough_ dan menuliskan _reducer_ sesuai dengan dokumentasi yang sudah disediakan oleh React JS. Di dalam reducer kita kirim 2 value yaitu text dan sending. Dengan demikian, implementasi _useOptimistic_ sudah bisa digunakan.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ebp9r43wsipbwj4xczn2.png)

Sekarang, kita bisa langsung gunakan _state useOptimistic_ pada html tag komponennya seperti kode program diatas. Bagaimana? cukup mudah bukan implementasi _useOptimistic Hooks_ ini pada React JS/Next JS?

Dengan menggunakan _useOptimistic Hooks_, sekarang aplikasi yang temen-temen kembangkan sudah memenuhi syarat minimal untuk meningkatkan _user experience_. Cukup sekian ya artikel sederhana yang bisa saya tuliskan, semoga kita bisa bertemu di artikel lain dengan materi yang lebih menarik lagi.