rustandbone Developer

React_zustand

테킷 멋쟁이사자처럼 React

zustand

import { create } from "zustand";

//store (define state & action)
const listStore = (set /* setState */) => {
  //return store's state & actions
  return {
    //state
    //Read - Query
    list: [
      {
        id: crypto.randomUUID(),
        title: "Zustand는 츄슈탄트로 발음한다",
      },
    ],

    //Write - Mutation
    addItem: (newItemTitle) =>
      set((state) => {
        return {
          list: [
            ...state.list,
            {
              id: crypto.randomUUID(),
              title: newItemTitle,
            },
          ],
        };
      }),

    deleteItem: (deleteId) =>
      set((state) => ({
        list: state.list.filter((item) => item.id !== deleteId),
      })),
  };
};

// hook (bind component) <- store (define state & action)
//훅을 만들어서 내보냄
export const useListStore = create(listStore);
<DisplayCount />
<AddItemControl />
<ItemList />

function DisplayCount() {
  const count = useCountStore((state) => state.count);
  return <output>{count}</output>
}

function AddItemControl() {
  const itemRef = useRef(null)

  //액션
  const addItem = useListStore((state) => state.addItem);
  const handleAddItem = () => {
    const newItemTitle = itemRef.current.value;
    addItem(newItemTitle);
    itemRef.current.value = '';
  }

  return (
    <div>
    <input ref={itemRef} type="text" aria-label="학습 주제 추가" placeholder='예) Zustand 발음 해보기'
      className='py-1 px-2 border-b border-b-slate-400 mr-2' />
    <button type="button" onClick={handleAddItem}>추가</button>
  </div>
  )
}

function ItemList() {
  const list = useListStore(
    /* 선택하는 기능 selector function - memoization : 성능 향상 */
    (state) => state.list);

  return (
    <ul className="my-8">
      {list?.map((item) => (
        <Item key={item.id} item={item} id={item.id} />
      ))}
    </ul>
  );
}

function Item({id}) {
  const item = useListStore(state => state.list.find(item => item.id === id));
  const deleteItem = useListStore((state) => state.deleteItem)

  const handleDeleteItem = (deleteId) => {
    deleteItem(deleteId)
  }

  return (
    <li>
      {item.title}{' '}
      <button type="button" onClick={() => handleDeleteItem(item.id)}>
        삭제
      </button>
    </li>
  );
}

ramda pipe

create(persist(immer(devtools(store))));
import pipe from "ramda/es/pipe";
import { createWithEqualityFn } from "zustand/traditional";
import { log } from "@/middlewares/log";
import { immer } from "@/middlewares/immer";
import { devtools, persist } from "zustand/middleware";

const withPersist = (config) => persist(config, { name: "app-store" });

const createStore = pipe(
  devtools,
  immer,
  log,
  withPersist,
  createWithEqualityFn
);

export default createStore;

사용하는 이유 :

  • pipe : 편리
  • devtools : 편리
  • immer : 편리
  • log : 편리
  • withPersist : 편리
  • 근거

모듈화 셀렉터 함수 자동 생성