🧸
zfy
  • Getting started
  • 🤓Guides
    • Creating & using a store
    • Persisting & rehydrating data
    • Using middlewares
    • Handling multiple stores
    • Type checking with TypeScript
  • 📚API reference
    • Types
      • CreateStoreType
      • CreateStoreConfigType
      • CreateStoreOptionsType
      • StoreType
      • ZfyMiddlewareType
      • InitStoresType
      • InitStoresResetOptionsType
    • createStore
    • initStores
    • PersistGate
    • useRehydrate
  • 🗃️Others
    • Help
    • Contributing
    • Changelog
    • GitHub
Powered by GitBook
On this page
  • API reference
  • stores
  • useStores

Was this helpful?

  1. API reference
  2. Types

InitStoresType

PreviousZfyMiddlewareTypeNextInitStoresResetOptionsType

Last updated 3 years ago

Was this helpful?

Interface representing the data structure of the method's output.

src/types.ts
import type { EqualityChecker } from 'zustand'

type InitStoresType<StoresDataType> = {
  stores: {
    [StoreNameType in keyof StoresDataType]: CreateStoreType<
      StoresDataType[StoreNameType]
    >
  } & {
    rehydrate: () => Promise<boolean>
    reset: (options?: InitStoresResetOptionsType<StoresDataType>) => void
  }
  useStores: <StoreNameType extends keyof StoresDataType, Output>(
    storeName: StoreNameType,
    selector: (data: StoresDataType[StoreNameType]) => Output,
    equalityFn?: EqualityChecker<Output>
  ) => Output
}

API reference

stores

  stores: {
    [StoreNameType in keyof StoresDataType]: CreateStoreType<
      StoresDataType[StoreNameType]
    >
  } & {
    rehydrate: () => Promise<boolean>
    reset: (options?: InitStoresResetOptionsType<StoresDataType>) => void
  }

stores.{storeName}

You can directly access all the zustand stores you provided to initStores() via the stores key. Example:

type StoresDataType = {
  nike: { name: string }
  fila: { name: string }
}

const nikeStore = createStore<StoresDataType['nike']>('nike', { name: 'Nike' })
const filaStore = createStore<StoresDataType['fila']>('fila', { name: 'fila' })

const { stores } = initStores<StoresDataType>([nikeStore, filaStore])

const nikeStoreName = stores.nike.getState().name // 'Nike'
const filaStoreName = stores.fila.getState().name // 'fila'

stores.rehydrate

type StoresDataType = {
  nike: { name: string }
  fila: { name: string }
}

const nikeStore = createStore<StoresDataType['nike']>('nike', { name: 'Nike' })
const filaStore = createStore<StoresDataType['fila']>('fila', { name: 'fila' })

const { stores } = initStores<StoresDataType>([nikeStore, filaStore])

await stores.rehydrate() // returns `true` upon completion

You shouldn't need to use this function as zustand stores rehydrate automatically:

stores.reset

Function that allows you to reset all (or part) of the stores you provided to initStores(). Example:

type StoresDataType = {
  fb: { company: string }
  ggl: { company: string }
}

const fbStore = createStore<StoresDataType['fb']>('fb', { company: 'Facebook' })
const googleStore = createStore<StoresDataType['ggl']>('ggl', { company: 'Google' })

const { stores } = initStores<StoresDataType>([fbStore, googleStore])

stores.fb.getState().update(data => {
  data.company = 'Meta'
})

stores.ggl.getState().update(data => {
  data.company = 'Alphabet'
})

stores.reset({ omit: ['fb'] })

stores.fb.getState().data.company === 'Meta' // true, fbStore was omitted 
stores.ggl.getState().data.company === 'Google' // true, googleStore was reset

stores.reset()

stores.fb.getState().data.company === 'Meta' // false, fbStore was reset as well now

useStores

  useStores: <StoreNameType extends keyof StoresDataType, Output>(
    storeName: StoreNameType,
    selector: (data: StoresDataType[StoreNameType]) => Output,
    equalityFn?: EqualityChecker<Output>
  ) => Output

React Hook that allows you to consume the data from any of the store you provided to initStores().

You'd use it exactly like you'd use a regular zustand store Hook, with the only difference that useStores() expects the name of the store you want to get data from as its initial argument. Example:

import shallow from 'zustand/shallow'

type StoresDataType = {
  wishlist: { nextPurchase: string }
  friends: { best: string }
}

const storeA = createStore<StoresDataType['wishlist']>('wishlist', {
  nextPurchase: 'Watch',
})
const storeB = createStore<StoresDataType['friends']>('friends', {
  best: 'TBD',
})

const { useStores } = initStores<StoresDataType>([storeA, storeB])

const Component = () => {
  const bestFriendName = useStores('friends', data => data.best) // TBD
  const nextItemToPurchase = useStores(
    'wishlist',
    data => data.nextPurchase,
    shallow
  ) // 'Watch'
  return null
}

useStores()really shines when you have a lot of stores in your app and don't want to have to import a lot of them/have a hard time remembering from which store you can get which data. You can now simply gather stores by topic/storage technology used/etc via initStores().

Promise that allows you to manually rehydrate all the stores provided to initStores() that have the middleware enabled. Example:

if you want to perform some actions upon rehydration, look into the PersistOptions.

if you want to hide/show your app depending on the rehydration status, see the component or the Hook.

📚
onRehydrateStorage
<PersistGate />
useRehydrate()
initStores()
persist
https://github.com/colorfy-software/zfy/blob/main/src/types.ts#L75-L89
import type {
  State,
  GetState,
  SetState,
  StoreApi,
  StateCreator,
  UseBoundStore,
  EqualityChecker,
} from 'zustand'
import type {
  PersistOptions,
  StoreApiWithPersist,
  StoreApiWithSubscribeWithSelector,
} from 'zustand/middleware'

export interface StoreType<StoreDataType> extends State {
  name: string
  data: StoreDataType
  reset: () => void
  update: (producer: (data: StoreDataType) => void) => void
}

export type CreateStoreType<StoreDataType> = UseBoundStore<
  StoreType<StoreDataType>
> & {
  persist?: StoreApiWithPersist<StoreType<StoreDataType>>['persist']
  subscribeWithSelector?: StoreApiWithSubscribeWithSelector<
    StoreType<StoreDataType>
  >['subscribe']
}

export type CreateStoreConfigType<
  StoreDataType,
  StoreApiType extends StoreApi<StoreType<StoreDataType>> = StoreApi<
    StoreType<StoreDataType>
  >
> = StateCreator<
  StoreType<StoreDataType>,
  SetState<StoreType<StoreDataType>>,
  GetState<StoreType<StoreDataType>>,
  StoreApiType
>

export interface CreateStoreOptionsType<StoreDataType> {
  log?: boolean
  subscribe?: boolean
  persist?: Omit<
    PersistOptions<StoreType<StoreDataType>>,
    'name' | 'blacklist' | 'whitelist'
  > & {
    name?: string
    getStorage: Exclude<
      PersistOptions<StoreType<StoreDataType>>['getStorage'],
      undefined
    >
  }
  customMiddlewares?: ZfyMiddlewareType<StoreDataType>[]
}

export type ZfyMiddlewareType<
  StoreDataType,
  StoreApiType extends StoreApi<StoreType<StoreDataType>> = StoreApi<
    StoreType<StoreDataType>
  >
> = (
  storeName: string,
  config: CreateStoreConfigType<StoreDataType>,
  options?: CreateStoreOptionsType<StoreDataType>
) => CreateStoreConfigType<StoreDataType, StoreApiType>

export type InitStoresResetOptionsType<StoreDataType> = {
  omit?: Array<keyof StoreDataType>
}

export type InitStoresType<StoresDataType> = {
  stores: {
    [StoreNameType in keyof StoresDataType]: CreateStoreType<
      StoresDataType[StoreNameType]
    >
  } & {
    rehydrate: () => Promise<boolean>
    reset: (options?: InitStoresResetOptionsType<StoresDataType>) => void
  }
  useStores: <StoreNameType extends keyof StoresDataType, Output>(
    storeName: StoreNameType,
    selector: (data: StoresDataType[StoreNameType]) => Output,
    equalityFn?: EqualityChecker<Output>
  ) => Output
}