테스트 코드를 돌리는 경우 zustand의 store들은 자동으로 초기화되지 않는다. 이러한 특징으로 인해 초기화되지 않은 state가 테스트에 영향을 줄 수 있다.
모든 테스트가 초기값을 가진 store에서 실행되기를 원한다면 test를 위한 mock zustand 코드를 구성해서 사용해야 한다.
import actualCreate, { StateCreator } from 'zustand'
// const actualCreate = jest.requireActual('zustand') // if using jest
import { act } from 'react-dom/test-utils'
// a variable to hold reset functions for all stores declared in the app
const storeResetFns = new Set<() => void>()
// when creating a store, we get its initial state, create a reset function and add it in the set
const create =
() =>
<S,>(createState: StateCreator<S>) => {
const store = actualCreate<S>(createState)
const initialState = store.getState()
storeResetFns.add(() => store.setState(initialState, true))
return store
}
// Reset all stores after each test run
beforeEach(() => {
act(() => storeResetFns.forEach((resetFn) => resetFn()))
})
export default create
zustand
=> __mocks__/zustand.js
에 파일 작성
zustand/vanila
=> __mocks__/zustand/vanilla.js
에 작성
이벤트 핸들러 밖에서 setState를 통해 state를 갱신하게 되면 리액트는 컴포넌트 업데이트를 동기적으로 수행한다. 이로 인해 zombie child 문제가 발생할 수 있다. 이를 막기 위해서는 unstabel_batchedUpdates
로 감싸야한다.
import { unstable_batchedUpdates } from 'react-dom' // or 'react-native'
const useFishStore = create((set) => ({
fishes: 0,
increaseFishes: () => set((prev) => ({ fishes: prev.fishes + 1 })),
}))
const nonReactCallback = () => {
unstable_batchedUpdates(() => {
useFishStore.getState().increaseFishes()
})
}
Zombie child refers specifically to the case where: