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 !