zustand 공식 문서 읽기 - 4

장동균·2022년 11월 23일
0

Tesing

테스트 코드를 돌리는 경우 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 에 작성


Calling actions outside a React event handler in pre React 18

이벤트 핸들러 밖에서 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:

  • Multiple nested connected components are mounted in a first pass, causing a child component to subscribe to the store before its parent
  • An action is dispatched that deletes data from the store, such as a todo item
  • The parent component would stop rendering that child as a result
  • However, because the child subscribed first, its subscription runs before the parent stops rendering it. When it reads a value from the store based on props, that data no longer exists, and if the extraction logic is not careful, this may result in an error being thrown.
profile
프론트 개발자가 되고 싶어요

0개의 댓글