Sederhanakan State Management di React App dengan Zustand

Haryana
5 min readApr 12, 2022

--

Hal apa yang terlintas ketika mendengar kata state management di react? Ya, Redux.
Redux begitu populer untuk implementasi state management di react.

Padahal banyak library state management pendatang baru yang cukup populer. seperti Recoil, Jotai, Radio Active state, dan Zustand.
Library tersebut menawarkan konsep simple, flexible, ease-to-use dan powerfull ̶s̶e̶r̶t̶a̶ ̶g̶r̶a̶t̶i̶s̶ ̶o̶n̶g̶k̶i̶r̶, yang berpotensi menggeser eksistensi Redux.

Di artikel ini kita akan meng-eksplor library Zustand.
Zustand ini library untuk mengatur global state yang mengklaim dirinya light-weight, boilerplatey or opinionated dan mengusung prinsip flux yang di sederhanakan.

Apa itu Zustand ?

Zustand bukan sebuah minuman olahan buah, bukan juga booth pameran apalagi kata singkatan zustand (zus s3tand).

Zustand adalah sebuah library opens-source yang mengatur state-management yang dikembangkan oleh Jotai dan creator react-spring, react-three-fiber. Sudah 343k download per minggu dan 16k star di github.

Dengan ukuran kurang lebih 1,73kb, dapat mengatasi beberapa masalah seperti:

1. zombie child problem
2. react concurrency
3. context loss.

Getting started with Zustand

Oke, kita langsung coba membuat proyek sederhana dengan menggunakan React.

Step 01: Installation

Hal yang utama yaitu, “pastikan niat dan tekad anda tidak kotak.
ini penting !

Kemudian mari kita buat proyek sederhana, dengan menjalankan perintah

npx create-react-app my-project 

Setelah selesai, masuk kedalam folder my-project

cd my-project

install Zustand.

npm install zustand

Step 02: Buat File Store

Pertama kita buat folder store dan di dalamnya kita buat file dengan nama useStore.js.

lalu kita buat code seperti ini:

markitkod ! mari kita koding.

// useStore.jsimport create from "zustand";const useStore = create((set) => ({
persons: ["john"],
addPerson: (person) => set((state) => ({
persons: state.persons.concat(person)
}))
}));
export default useStore;

Function utama untuk membuat store pada library ini yaitu create.
Menerima callback function pada argument pertama yang disebut set

Fungsi create ini kemudian mengembalikan fungsi lain, dalam kasus ini disebut useStore.
Seperti yang kita lihat contoh diatas, ia mengembalikan sebuah hook, sehingga kita dapat memanggil di komponent mana saja.

oke lanjut…

Step 03: Implementasi data Store kedalam Component.

Selanjutnya bagaimana data store itu bisa di panggil kedalam komponen ?

Pertama buka file App.js lalu kita import file useStore :

// App.jsimport  React from  'react';
import useStore from './store/useStore';
// ...
function App() {
const persons = useStore(state => state.persons);

Kemudian tampilkan data list persons

// App.jsimport  React from  'react';
import useStore from './store/useStore';
import './App.css';
function App() {
const persons = useStore(state => state.persons);

return (
<div className="App">
<h2>List person: </h2>
{persons.map(person => (
<div>- {person}</div>
))}
</div>
);
}
export default App;

akan terlihat seperti ini:

Oke, setelah kita berhasil menampilkan list persons, mari kita coba tambah value kedalam global store persons.

Pertama kita panggil method addPerson.

// App.jsimport  React, { useState } from  'react';
import useStore from './store/useStore';
import './App.css';
function App() {
const persons = useStore(state => state.persons);
// call method addPerson
const addPerson = useStore(state => state.addPerson);
// ...

Buat form input beserta handler nya :

// App.jsimport  React, { useState } from  'react';
import useStore from './store/useStore';
import './App.css';
function App() {
const persons = useStore(state => state.persons);
const addPerson = useStore(state => state.addPerson);
const [person, setPerson] = useState('')
const handleAddPerson = (e) => {
e.preventDefault()
addPerson(person)
setPerson('')
}
return (
<div className="App">
<form onSubmit={handleAddPerson}>
<input
required
value={person}
onChange={(e) => setPerson(e.target.value)}
/>
<button type="submit">(+) Add person</button>
</form>
<h2>List person: </h2>
{persons.map(person => (
<div>- {person}</div>
))}
</div>
);
}
export default App;

hasilnya akan seperti ini:

Pada global store kita mempunyai beberapa element, yaitu state dan action.
Kemudian kita panggil state persons kedalam App.js, dan kita tampilkan dalam bentuk list.
Disini juga kita dapat menambahkan value kedalam global store persons dengan memanggil action addPerson .

Action addPerson akan bereaksi ketika button (+) Add person di klik, dan akan mengirim data form input untuk disimpan ke global store.

Pada saat itu pula list data persons akan terupdate.

Step 04: Implementasi async action / fetch data API

“ Lalu gimana sih, implementasi async action / fetch data di zustand ? ”

oke markitkod !

// useStore.jsimport create from "zustand";const URL = "https://jsonplaceholder.typicode.com/users";const useStore = create((set) => ({
persons: ["john"],
addPerson: (person) => set((state) => ({
persons: state.persons.concat(person)
})),

// fetching api
getPersons: async () => {
const response = await fetch(URL);
const data = await response.json()
set({ persons: data.map(item=>item.name) })
}
}));
export default useStore;

Async action dapat di handle menggunakan async/await pada javascript.
Dari kode di atas, Zustand lebih lugas dan simple untuk implementasinya.
bagaimana tidak, fetching data di async action dapat dengan mudah di handle tanpa adanya syarat khusus ataupun sesajen.

lancar! berasa masuk tol jakarta pas lebaran.

Step 05: Middleware ? ada gitu ?

yups ! zustand juga punya middleware.
Menurut saya ini unik, salah satunya yaitu persist dan devtools.

Persist state

Oke kita bahas persist dulu.
Dengan persist, kita bisa membuat data menjadi persistance di browser dan dapat di aplikasikan menggunakan storage apapun.

Untuk contoh ini, kita buat menggunakan sessionStorage.

import create from "zustand"
import { persist } from "zustand/middleware"
export const useStore = create(persist(
(set) => ({
persons: [],
addPerson: (person) => set((state) => ({
persons: state.persons.concat(person)
})),
// ...others

}),
{
name: "person-storage", // unique key name
getStorage: () => sessionStorage, // (optional) by default the 'localStorage' is used
}
))

Redux devtools

Dengan zustand, kita juga dapat menggunakan ekstensi redux devtools. Yang diperlukan hanyalah mengimportnya dari zustand/middleware.

let’s code !

import create from 'zustand'
import { devtools } from 'zustand/middleware'
export const useStore = create(devtools(set => ({
persons: [],
addPerson: (person) => set((state) => ({
persons: state.persons.concat(person)
})),
// ...others
})))

Conclusion

Dari contoh yang sudah kita buat, zustand ini sangat sederhana dan mudah untuk di implementasikan.

Zustand juga bisa di implementasikan tanpa ada ketergantungan dengan React, artinya dengan menggunakan vanillaJs pun kita dapat menggunakan zustand.

Menurut saya, zustand ini patut di perhitungkan untuk bersaing di kancah per-state managament-an dengan library lain yang sudah eksis.

Kesederhanaan library ini juga menjadikan pilihan yang baik untuk pemula khususnya implementasi state management dengan React.
Terlepas dari kemudahan itu, mungkin ada beberapa keterbatasan salah satunya dokumentasi. Hanya mempunyai dokumentasi utama yaitu readme.md pada githubnya. Untuk sekarang cukup bisa di pahami.

Dari penjelasan diatas mudah-mudahan dapat menjadi bahan pertimbangan untuk memilih state management yang cocok dengan proyek yang sedang anda kerjakan.

Sekali lagi, opini diatas hanya berdasarkan dari pengalaman saya pribadi.
Bila ada ketidaksesuaian dalam penulisan mohon di maklumi.
Ingin berdiskusi ? hubungi saya.

Last !
pepatah thailand mengatakan

khup nai lay, pha thung pong
artinya
Tersenyumlah, karena senyum itu smile.

Terima kasih.
Cheers !

--

--