Skip to main content

injectStore

import { injectStore } from '@zedux/react'

An injector that creates and returns a stable Zedux store. This reference will not change on subsequent evaluations of this atom instance.

injectStore() is the injector equivalent of both useState() and useReducer(), since Zedux stores cover both use cases (and more).

Examples

Live Sandbox
1234567891011121314151617
const secondsAtom = atom('seconds', () => {
const store = injectStore(0)

injectEffect(() => {
const intervalId = setInterval(() => store.setState(val => val + 1), 1000)

return () => clearInterval(intervalId)
}, [])

return store
})

function Seconds() {
const state = useAtomValue(secondsAtom)

return <div>Seconds: {state}</div>
}

Miscellaneous:

import { createStore, injectStore } from '@zedux/react'

const zeroConfigStore = injectStore('initial state')
const createdManually = injectStore(() => createStore(null, 'initial state'))
const configuredStore = injectStore(() => createStore(rootReducer))

const composedStore = injectStore(() =>
createStore({
zeroConfig: zeroConfigStore,
configured: configuredStore,
})
)

const nonSubscribingStore = injectStore('state', { subscribe: false })
const hydratedStore = injectStore('default', { hydrate: true })
const hydratedManually = injectStore(
hydration => createStore(null, hydration ?? 'default'),
{ hydrate: true }
)
const withExpensiveInitialState = injectStore(() =>
createStore(null, calculateExpensiveValue())
)

Prefer store.use()

When creating a store composed of child stores and/or reducers, you may think to do it like this:

const store = injectStore(() =>
createStore({
a: storeA,
b: storeB,
})
)

This is fine if the child store references are stable. A common case where store references are technically unstable is when using stores injected from other atoms:

const storeA = injectAtomInstance(atomA).store
const storeB = injectAtomInstance(atomB).store

Since atom instances can be force-destroyed, these stores are technically unstable references. To keep these references up-to-date in the parent store, prefer store.use():

const store = injectStore()
store.use({
a: storeA,
b: storeB,
})

store.use() does nothing if the hierarchy hasn't changed, so this will be a noop on reevaluations where the child stores are unchanged.

note

While it's supported and we have found use cases for composing together stores from different atom instances like this, we don't recommend it. If you can possibly avoid it, do.

Signature

injectStore = (valueOrFactory?, config?) => store
valueOrFactory

Optional. The initial value of the store or a factory function that returns a store using createStore().

This value will be ignored after the first evaluation of the current atom instance.

config

Optional. An object with the following optional properties:

{ hydrate, subscribe }
hydrate

Optional. Boolean. Default false. Whether to use a hydration passed to ecosystem.hydrate() as the initial state of the store.

Does nothing if the ecosystem doesn't have a hydration that matches the current atom instance.

If true, calls this atom's hydrate config option (if any) to transform the hydrated value, then sets the transformed value as the initial state of the store.

If the factory function overload is used, the transformed hydration will be passed to the factory. It's up to you to use the hydrated value to initialize your store's state.

subscribe

Optional. Boolean. Default true. Whether state updates in this store should trigger reevaluations of the current atom.

You should leave this alone unless you absolutely need to fine-tune performance in your app. Messing with reactivity can lead to hard-to-find bugs.

Returns

A Zedux store. If using the function overload, this will be the store you returned.

This store is a stable reference - the reference will not change on subsequent evaluations.

See Also