PROA

Professional Academy

React - Zustand

Agenda

Apa saja yang akan dibahas?

  • Revisiting Redux (Toolkit)
  • Revisiting RTK Query
  • Zustand
    • Intro
    • What Is?
    • How to?
    • Demo
    • Bonus (Simple Loader)
  • Conclusion
  • QnA
  • Referensi

Revisiting Redux (Toolkit)

Masih ingat bagaimana cara menggunakan RTK?

Mari kita coba lihat kembali kode yang terakhir dituliskan di sini dan mengingat langkah apa saja yang sudah dilakukan:

  1. Menginstall RTK terlebih dahulu npm i @reduxjs/toolkit react-redux
  2. Membuat sebuah slice untuk fitur yang ingin digunakan (/src/features/sliceCounter.js)
  3. Membuat store (/src/app/store.js)
  4. Mem-Provide store yang dibuat pada entry point aplikasi (index.js)
  5. Menggunakan state dan action dari slice pada Component berdasarkan logic yang ingin dirancang

Dan... selesai, kita sudah berhasil menggunakan Redux Toolkit dengan baik !

WARNING: ini hanyalah langkahnya saja, sebenarnya kode yang ditulis cukup banyak.

Revisiting RTK Query

Bagaimanakah bila kita ingin melakukan penarikan data dari external (API) pada saat menggunakan RTK?

Salah satu solusi yang diberikan dari RTK, adalah dengan menggunakan RTK Query

Mari kita coba lihat kembali kode yang terakhir dituliskan di sini dan mengingat langkah apa saja yang sudah dilakukan:

  1. Membuat sebuah services terlebih dahulu berdasarkan API yang ingin ditembak (/src/services/reqresinAPI)
  2. Mencantolkan services yang dibuat pada store (/src/app/store.js) dalam bentuk reducer dan middleware
  3. Menggunakan logic yang dibuat pada Component yang ada DALAM BENTUK HOOKS yang dibuatkan secara otomatis pada saat membuat services

Dan... selesai, kita sudah berhasil menggunakan RTK Query dengan baik !

WARNING: ini hanyalah langkahnya saja, sebenarnya kode yang ditulis cukup banyak.

Zustand - Intro

Cukup menyulitkan bukan menggunakan Redux Toolkit dan RTK Query ini?

Jadi bagaimana apabila kita ingin membuat sebuah project yang menggunakan state management?

Apakah harus selalu menggunakan boilerplate dan template yang sebanyak ini?

Apakah ada solusi lainnya untuk State Management selain Redux Toolkit ini?

Please welcome ... Zustand

Zustand - What Is?

Dikutip dari halaman Github-nya Zustand

Zustand adalah solusi state management yang kecil, cepat, dan bisa di-scale yang menggunakan prinsip flux, berbasis hooks, tidak terlalu ber-boilerplate ataupun teropini !

Pssttttt..... cara penggunaan Zustand bisa jadi JAUH lebih mudah ketimbang menggunakan Redux Toolkit

(Apabila tidak memikirkan RTK Query-nya)

Zustand - How To?

Cara menggunakan Zustand pun tidak terlalu sulit:

  • Install zustand terlebih dahulu dengan npm i zustand
  • Membuat store-nya terlebih dahulu
  • import create from "zustand";
    
    const useCounterStore = create((set) => ({
      // state
      counter: 0,
      // "action"
      increaseCounter: () => set((state) => ({ counter: state.counter + 1 })),
    }));
    
    // selector state & action
    export const selectCounter = (state) => state.counter;
    export const selectActionIncreaseCounter = (state) => state.increaseCounter;
    
    export default useCounterStore;

Zustand - How To?

  • Gunakan di dalam Component
  • import useCounterStore, {
      selectCounter,
      selectActionIncreaseCounter,
    } from "./stores/counter";
    
    function App() {
      // gunakan layaknya hooks, cari state dengan cara selector
      const counter = useCounterStore(selectCounter);
    
      // gunakan layaknya hooks, cari action dengan cara selector juga
      const increaseCounter = useCounterStore(selectActionIncreaseCounter);
    
      return (
        <div className="App">
          <h1>Current Counter: {counter}</h1>
          <button onClick={() => increaseCounter()}>Increase</button>
        </div>
      );
    }
    
    export default App;
  • Dan selesai !
  • Lebih mudah bukan menggunakannya?

Zustand - How To? (Async)

Bagaimanakah kasusnya bila kita ingin memiliki suatu data yang didapatkan dari external seperti dari API?

Apakah harus menggunakan Middleware seperti kita menggunakan RTK Query?

Jawaban pendeknya adalah: TYDAQUE !

Zustand tidak peduli apakah suatu "action" yang dibuat adalah bersifat async ataupun tidak. Keduanya bisa digunakan bersamaan

a.k.a Tinggal declare saja !

Psssstttttt.... tapi kita jadi butuh axios lagi nih.

Zustand - How To? (Async)

Misalkan kita ingin mengambil data dari JSONPlaceholder (Posts), maka yang dilakukan adalah:

  • Membuat store-nya terlebih dahulu
  • import axios from "axios";
    import create from "zustand";
    
    const useJSONPlaceholderStore = create((set) => ({
      // state awal berupa sebuah array kosong
      posts: [],
      // action yang bersifat async
      getPosts: async () => {
        // asumsi selalu berhasil, tidak ada try catch
        const response = await axios.get(
          "https://jsonplaceholder.typicode.com/posts"
        );
        // selesai fetch data akan menuliskan ulang state posts
        set({ posts: response.data });
      },
    }));
    
    // selector state dan action
    export const selectPosts = (state) => state.posts;
    export const selectActionGetPosts = (state) => state.getPosts;
    
    export default useJSONPlaceholderStore;

Zustand - How To? (Async)

  • Menggunakannya di Component
  • import React, { useEffect } from "react";
    import useJSONPlaceholderStore, {
      selectPosts,
      selectActionGetPosts,
    } from "./stores/jsonplaceholder";
    
    function App() {
      // gunakan layaknya hooks, cari state dengan cara selector
      const posts = useJSONPlaceholderStore(selectPosts);
      // gunakan layaknya hooks, cari action dengan cara selector juga
      const getPosts = useJSONPlaceholderStore(selectActionGetPosts);
      // Karena ingin dipanggil saat pertama kali Component ada, gunakan useEffect
      useEffect(() => {
        getPosts();
      }, []);
      return (
        <div className="App">
          <ul>
            {posts.map((post) => (
              <li key={post.id}>{post.title}</li>
            ))}
          </ul>
        </div>
      );
    }
    
    export default App;

Zustand - Demo

Yuk sudah cukup kita lihat "Intro Zustand" tadi

Mari sekarang kita demo:

Mengkonversi aplikasi yang sebelumnya dibuat dengan Redux Toolkit menjadi versi Zustand !

Langkah-langkah pengerjaannya adalah sebagai berikut: (Simple Counter)

  1. Clone starter pack yang akan digunakan di sini
  2. Install seluruh package yang harus digunakan dengan npm install
  3. Install package tambahan (Zustand) dengan npm install zustand
  4. Membuat sebuah file store /src/stores/counter.js
  5. Menggunakan store tersebut pada /src/containers/CounterZustandContainer.jsx
  6. Dan selesai, Aplikasi Counter kita pun sudah bisa berjalan dengan baik !

Langkahnya sedikit namun kodenya lumayan loh yah !

Untuk melihat kodenya bisa diintip di sini yah

Zustand - Demo

Mari sekarang kita mencoba untuk melakukan fetch data dari reqres.in API yah

Langkah-langkah pengerjaannya adalah sebagai berikut: (Fetch User)

  1. Membuat sebuah file store /src/stores/user.js
  2. Menuliskan state, action, hooks, serta selector yang digunakan
  3. Menggunakan store tersebut pada /src/containers/CounterZustandContainer.jsx
  4. Dan selesai, Aplikasi fetch data users dari API reqres.in kita pun sudah bisa berjalan dengan baik

Langkahnya sedikit namun kodenya lumayan loh yah !

Untuk melihat kodenya bisa diintip di sini yah

Zustand - Demo

Sekarang mari kita coba untuk menyelesaikan fetch data colors dari reqres.in API yah

Tapi sekarang kita punya syarat: datanya ingin kita buat "seperti mutable"

Masih ingat dengan RTK yang bisa membuat perubahan statenya "seperti mutable" dengan apa?

Ya, dengan immer !

Langkah-langkah pengerjaannya adalah sebagai berikut: (With Immer)

  1. Menginstall immer dengan npm i immer
  2. Membuat sebuah file store /src/stores/color.js
  3. Menggunakan immer dalam memutasikan state yang dibuat
  4. Menggunakan store tersebut pada /src/components/ColorListZustand.jsx
  5. Dan selesai, Aplikasi Fetch Colors dengan menggunakan Immer sudah bisa berjalan dengan baik !

Langkahnya sedikit namun kodenya lumayan loh yah !

Untuk melihat kodenya bisa diintip di sini yah

Zustand - Demo (Conclusion)

Dan selesai sudah untuk demo yang kita lakukan ini.

Dengan demikian kita sudah berhasil membuat aplikasi yang mirip dengan versi RTK dan RTK Query, namun dengan menggunakan Zustand

Bagaimana, apakah dengan menggunakan Zustand lebih baik? ataukan menggunakan RTK + RTK Query lebih enak?

Teman-teman sebagai developer yang pada akhirnya menentukan yah "enakan" yang mana?

Zustand - Bonus (Simple Loader)

Nah dari tadi kita menggunakan Zustand tanpa ada "Loading" nya sama sekali yah ...

Karena memang dalam Zustand, tidak ada "Loading" yang bisa digunakan secara langsung !

Lalu apabila seperti itu kita harus bagaimana bila ingin membuat semacam "Loading" dengan Zustand ini?

Jawabannya adalah: dengan menggunakan sedikit "logic"

Mari kita coba membuatnya untuk fetch data user yah !

Zustand - Bonus (Simple Loader)

Langkah-langkah pengerjaannya adalah sebagai berikut: (Simple Loaders)

  1. Membuat file store /src/stores/userWithLoader.js
  2. Memasukkan store tambahan dengan nama loading dan error
  3. Modifikasi file /src/containers/CounterZustandContainer.jsx
  4. Dan selesai, kita sudah berhasil menggunakan Loader dengan logic sederhana, menakjubkan bukan?

Untuk melihat kodenya bisa diintip di sini yah

QnA

Referensi

  • https://github.com/pmndrs/zustand
withered-flowers (2022)