Implementasi useReducerAtom Jotai

avatar

Haikel, 3 min read / May 29, 2023

بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ

Pendahuluan

useReducer adalah sebuah React Hook yang fungsinya serupa dengan useState, tapi biasa digunakan untuk kasus yang lebih kompleks, juga cara penggunaannya yang berbeda.

Di jotai juga, punya hal serupa yang bernama useReducerAtom. Konsepnya sama saja dengan useReducer biasa, hanya saja initialState ama reducernya dibalik.

Jadi kurang lebih begini gambarannya:

const [state, dispatch] = useReducerAtom(initialAtom, reducer);

Nah jadi si initialState nya(dalam hal ini initialAtom) berada di depan, kemudian diikuti dengan fungsi reducer nya. initialState mesti bernilai atom yang disediakan jotai. Kalau temen-temen pake typescript, pasti bakal ngedetect Error jika tidak pakai atom. Contoh:

Error initialState

Padahal jika saya pakai useReducer biasa, dia ga bakal error

useReducer

Implementasi

Disini saya coba implementasi ke operasi matematika sederhana(tambah, kurang). Sebagai catatan, di project saya sudah terinstall chakra-ui untuk styling. Emang Overkill sih hehe, tapi kalo buat keperluan ngetest doang mah gapapa.

App.tsx
import { Button, Container, Flex, Text } from "@chakra-ui/react";
import { atom } from "jotai";
import { useReducerAtom } from "jotai/utils";
 
function reducer(state: { value: number }, action: { operation: "TAMBAH" | "KURANG" }) {
  switch (action.operation) {
    case "TAMBAH":
      return {
        value: state.value + 1,
      };
 
    case "KURANG":
      return {
        value: state.value - 1,
      };
 
    default:
      throw new Error();
  }
}
 
const reducerAtom = atom<{ value: number }>({ value: 0 });

Fokus di bagian fungsi reducer, saya pakai switch case untuk pengkondisian. Pake if else juga bisa.

  • Jika operation nya bernilai "TAMBAH", maka nilai akan bertambah 1.
  • Jika operation nya bernilai "KURANG", maka nilai akan berkurang 1.
  • Jika nilainya selain itu, maka akan mencetak pesan Error.

Saya juga menginisialisasi reducerAtom sebagai initialAtom.

Oke mari kita lanjut

App.tsx
export default function App() {
  const [state, dispatch] = useReducerAtom(reducerAtom, reducer);
 
  return (
    <Container>
      <Flex justify="center" h="100vh" alignItems="center" flexDir="column">
        <Flex gap={3}>
          <Button onClick={() => dispatch({ operation: "TAMBAH" })}>+</Button>
          <Text>{state.value}</Text>
          <Button onClick={() => dispatch({ operation: "KURANG" })}>-</Button>
        </Flex>
      </Flex>
    </Container>
  );
}

Seperti yang sudah saya singgung di awal, useReducerAtom agak berbeda dengan useReducer biasa. Di dalam useReducerAtom, kita memasukkan nilai reducerAtom dan fungsi reducer.

Keseluruhan code:

App.tsx
import { Button, Container, Flex, Text } from "@chakra-ui/react";
import { atom } from "jotai";
import { useReducerAtom } from "jotai/utils";
 
function reducer(state: { value: number }, action: { operation: "TAMBAH" | "KURANG" }) {
  switch (action.operation) {
    case "TAMBAH":
      return {
        value: state.value + 1,
      };
 
    case "KURANG":
      return {
        value: state.value - 1,
      };
 
    default:
      throw new Error();
  }
}
 
const reducerAtom = atom<{ value: number }>({ value: 0 });
 
export default function App() {
  const [state, dispatch] = useReducerAtom(reducerAtom, reducer);
 
  return (
    <Container>
      <Flex justify="center" h="100vh" alignItems="center" flexDir="column">
        <Flex gap={3}>
          <Button onClick={() => dispatch({ operation: "TAMBAH" })}>+</Button>
          <Text>{state.value}</Text>
          <Button onClick={() => dispatch({ operation: "KURANG" })}>-</Button>
        </Flex>
      </Flex>
    </Container>
  );
}

Jika dijalankan, maka akan seperti ini:

Penutup

Yep, mungkin sekian untuk tulisan kali ini. Semoga bermanfaat :)

Referensi