zustand

Jinmin Kim·2024년 1월 17일

zustand

zustand 기본 설정

//index.js
const store = (set, get) => ({
    ...state,
    ...handler(set,get)
})

const myStore = create(
    process.env.NODE_ENV !== 'production' ? devtools(store) : store
);

export default myStore;

zustand 값 변경

1. getState, setState로 설정

const {
     getTree
   , getlist
    } = commonStore.getState();
    // 다른 store에서 가져올때
    
 const {
            treeList
        } = get(); 
    // 나의 store에서 가져올때
    
    
//1.store의 값을 변경하고 싶을때(내부 메소드를 지정해서 사용)
commonStore.getState()
			.setStore({barOpen:false});
            
//2.store의 값을 변경하고 싶을때(기존 setState로 가능)
commonStore.setState({
                message: "권한 부여가 완료되었습니다."
                , barOpen: true
                , barType: "success"
})

*** 2. handler로 변경

2번을 추구하는이유
1. state의 불변성 = 다른 개발자가 state를 사용하여서 쉽게 다른값을 사용하지 않게 하는 이유 및 방법
2. obj의 depth가 늘어낫을경우에 이전의 리스트를 가져와서 하나하나의 값을 넣어주어야 한다.

  • state.js
const testState = {
	test : ""
};

export default testState;
  • handler.js
const testHandler = (set,get) => ({
    getList: async () => {
         const result = await API.getList();
         // set의 메소드를 가지고 state.js의 state인 test값을 변경가능
         set({test: ""});
    },
});

또한 라이브러리 immer의 produce값 사용으로 값 불변성 유지

import {produce} from 'immer';
//...
    setTest: (obj) => {
        set(produce((state) => {
            Object.entries(obj).forEach(([key, value]) => {
                state[key] = value;
            })
        }))
    },

zustand 사용

"setComparsionDataIndex"와 같이 지정해주면 아래와 같이
redux devtools에서 zustand와 호환이 되는데,
handler의 정확한 네이밍을 알려줄수있어서 좋다.

setComparsionDataIndex: (newData: Partial<any>, index: number) => {
        set((prev) => {
            return produce(prev, (draft) => {
                draft.state.data[index] = newData;
            });
        }, false, "setComparsionDataIndex");
    },

아래와 같은 { name: 'ComparsionStore'}을 추가하게되면
정확한 네이밍을 위의 그림에서 처럼 알려주기때문에 유용하다.

devtools(
        (set, get) => ({
            state: {
                ...state, // 상태 초기화
            },
            handler: handler(set, get),
        }),
        { name: 'ComparsionStore'} //redux devtools에서 name에 지정한 instance로 확인할 수 있다.
    )

zustand의 랜더링

  • 구독(subscribe)과 리렌더링:
    • useStore 훅이나 Zustand의 hook을 사용하여 특정 state(또는 그 일부)를 구독하면, 그 구독한 값이 변경될 때마다 해당 컴포넌트는 리렌더링됩니다.
    • 만약 구독한 state를 실제 렌더링에서 사용하지 않더라도, 구독 자체가 이루어지면 값이 변경될 때 리렌더링이 발생합니다.
  • Selector 사용의 중요성:
    • 상태 전체를 구독하는 대신 필요한 일부만 선택(selector)하면, 선택한 값이 변경될 때만 리렌더링이 발생합니다.
    • 예를 들어, 아래와 같이 특정 부분만 구독하면 다른 부분이 변경되더라도 해당 컴포넌트는 리렌더링되지 않습니다.
const serviceNameOption = useStore(
  (state) => state.optionsData.serviceName,
  shallow  // 얕은 비교를 통해 값이 바뀌었을 때만 리렌더링
);
  • 만약 selector 없이 전체 상태를 가져오면, 아무리 사용하지 않더라도 전체 상태가 바뀔 때마다 구독한 컴포넌트는 리렌더링됩니다.
profile
Let's do it developer

0개의 댓글