zustand - 从多个 store 取值, 避免重渲染

766 阅读1分钟
import useSyncExternalStoreExports from 'use-sync-external-store/shim/with-selector'

const { useSyncExternalStoreWithSelector } = useSyncExternalStoreExports

export const useCombinedStores = (
  apis: any[],
  selectors: (...rest: any[]) => any[],
  equalityFn?: (left: any[], right: any[]) => boolean
) => {
  const subscribe = (listener: () => void) => {
    const unsubs = [] as (() => void)[]
    apis.forEach((api) => {
      const unsub = api.subscribe(listener)
      unsubs.push(unsub)
    })

    return () => {
      unsubs.forEach((unsub) => unsub())
    }
  }

  const getState = () => {
    return apis.map((api) => api.getState())
  }

  const selector = (...states: any[]) => {
    return selectors(...states)
  }

  const slices = useSyncExternalStoreWithSelector(
    subscribe,
    getState,
    getState,
    selector,
    equalityFn
  )
  useDebugValue(slices)
  return slices
}