문서에서는 이 둘의 타입을 구분하여 작성하고 있음. 이러한 방식이 프로퍼티를 확인하기에 더 편할 수도?
type State = {
firstName: string
lastName: string
}
type Action = {
updateFirstName: (firstName: State['firstName']) => void
updateLastName: (lastName: State['lastName']) => void
}
const useStore = create<State & Action>((set) => ({
firstName: '',
lastName: '',
updateFirstName: (firstName) => set(() => ({ firstName: firstName })),
updateLastName: (lastName) => set(() => ({ lastName: lastName })),
}))
immer
, optisch-ts
, Ramda
를 사용하는 방법이 존재
immer를 사용하는 방식이 가장 대중적
zustand의 store 안에 저장된 state들은 immutable하다. 때문에 값을 갱신해야할 때 원래는 다음과 같은 구문으로 작성해야한다.
set((state) => ({ ...state, count: state.count + 1 }))
하지만 zustand의 set 함수는 자체적으로 state를 머지하기 때문에 spread operator의 사용이 불필요하다.
(내부적으로 Object.assign({}, state, nextState)
로 처리하기 때문에 immutable
한 새로운 객체 안에서 값들이 병합된다.)
하지만 중첩인 경우 문제가 생김. spread operator
혹은 immer
를 사용할 필요가 있음.
const { secondNumber } = useStore();
다음과 같이 구문을 작성하면 useStore
내부의 무엇이 바뀌든 secondNumber
를 사용하는 컴포넌트들은 리렌더가 일어남.
secondNumber
가 변할 때만 리렌더를 일으키고 싶다면 값을 가져올 때 다음과 같이 가져올 필요가 있음
const secondNumber = useStore(state => state.secondNumber);