### Install Zedux React Package
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/quick-start.mdx
This snippet provides commands for installing the `@zedux/react` package using popular Node.js package managers: npm, yarn, and pnpm. This package includes the core Zedux store and atomic models, along with React-specific APIs. It has a peer dependency on React 18+.
```bash
npm install @zedux/react # npm
yarn add @zedux/react # yarn
pnpm add @zedux/react # pnpm
```
--------------------------------
### Basic @zedux/atoms Usage Example
Source: https://github.com/omnistac/zedux/blob/master/packages/atoms/README.md
Demonstrates how to create an atom, initialize an ecosystem, get an atom instance, subscribe to state changes, update the atom's state, and destroy the instance.
```tsx
import { atom, createEcosystem } from '@zedux/atoms'
const greetingAtom = atom('greeting', 'Hello, World!')
const ecosystem = createEcosystem({ id: 'root' })
const instance = ecosystem.getNode(greetingAtom)
instance.on('change', ({ newState }) => console.log('state updated:', newState))
instance.set('Goodbye, World!')
instance.destroy()
```
--------------------------------
### Basic Python Print Example
Source: https://github.com/omnistac/zedux/blob/master/docs/style-guide.md
A simple Python code block illustrating variable assignment and the use of the 'print' function to output a string to the console.
```python
s = "Python syntax highlighting"
print(s)
```
--------------------------------
### Untyped Code Block Example
Source: https://github.com/omnistac/zedux/blob/master/docs/style-guide.md
An example of a code block where no specific programming language is indicated. It demonstrates how plain text, including HTML tags, would appear without syntax highlighting.
```text
No language indicated, so no syntax highlighting.
But let's throw in a tag.
```
--------------------------------
### Basic JavaScript Alert Example
Source: https://github.com/omnistac/zedux/blob/master/docs/style-guide.md
A fundamental JavaScript snippet demonstrating variable declaration and assignment, followed by the use of the 'alert' function to display a message in a browser dialog.
```javascript
var s = 'JavaScript syntax highlighting'
alert(s)
```
--------------------------------
### Basic @zedux/stores Usage with Atom and Ecosystem
Source: https://github.com/omnistac/zedux/blob/master/packages/stores/README.md
A basic example demonstrating how to use @zedux/stores to create an atom, initialize an ecosystem, get an atom instance, subscribe to its state, update the state, and destroy the instance. This showcases the core store functionality.
```tsx
import { atom, createEcosystem } from '@zedux/stores'
const greetingAtom = atom('greeting', 'Hello, World!')
const ecosystem = createEcosystem({ id: 'root' })
const instance = ecosystem.getInstance(greetingAtom)
instance.store.subscribe(newState => console.log('state updated:', newState))
instance.setState('Goodbye, World!')
instance.destroy()
```
--------------------------------
### Install @zedux/react and @zedux/machines for React apps
Source: https://github.com/omnistac/zedux/blob/master/packages/machines/README.md
Commands to install `@zedux/react` and `@zedux/machines` for use in React applications. Note that `@zedux/react` already includes `@zedux/atoms`, so it's not necessary to install `@zedux/atoms` separately in this context.
```sh
npm install @zedux/react @zedux/machines # npm
```
```sh
yarn add @zedux/react @zedux/machines # yarn
```
```sh
pnpm add @zedux/react @zedux/machines # pnpm
```
--------------------------------
### Examples of createEcosystem Usage
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/factories/createEcosystem.mdx
Demonstrates various ways to use the `createEcosystem` function. Examples include creating a basic ecosystem with an ID, applying atom overrides, and utilizing the `onReady` callback to perform actions like preloading atoms when the ecosystem is initialized.
```ts
import { createEcosystem } from '@zedux/react'
const rootEcosystem = createEcosystem({ id: 'root' })
const withOverrides = createEcosystem({
id: 'withOverrides',
overrides: [atomA, atomB],
})
const withOnReadyFn = createEcosystem({
id: 'withOnReadyFn',
onReady: ecosystem => {
// `onReady` is passed a reference to the ecosystem
ecosystem.getInstance(myAtom) // preload myAtom
},
})
```
--------------------------------
### Install @zedux/immer with @zedux/atoms
Source: https://github.com/omnistac/zedux/blob/master/packages/immer/README.md
Instructions for installing `@zedux/immer` along with its peer dependencies `immer` and `@zedux/atoms` for general Zedux applications.
```sh
npm install immer @zedux/atoms @zedux/immer
```
```sh
yarn add immer @zedux/atoms @zedux/immer
```
```sh
pnpm add immer @zedux/atoms @zedux/immer
```
--------------------------------
### Install Docusaurus 2 Website Dependencies
Source: https://github.com/omnistac/zedux/blob/master/docs/README.md
This command installs all necessary project dependencies using Yarn. It should be executed once after cloning the repository to set up the development environment.
```shell
$ yarn
```
--------------------------------
### Install @zedux/atoms Package
Source: https://github.com/omnistac/zedux/blob/master/packages/atoms/README.md
Commands to install the `@zedux/atoms` package using various Node.js package managers.
```sh
npm install @zedux/atoms
```
```sh
yarn add @zedux/atoms
```
```sh
pnpm add @zedux/atoms
```
--------------------------------
### Full Example: Theme Toggle with Zedux State Machine
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/injectMachineStore.mdx
A complete, runnable example demonstrating `injectMachineStore` in a practical scenario. It defines a `themeAtom` that uses a state machine to manage 'light' and 'dark' modes, including context updates for a toggle count. The example integrates with a React component (`Theme`) to display and control the theme, showcasing how to send events and consume state machine output.
```tsx
const themeAtom = atom('theme', () => {
const store = injectMachineStore(
state => [
state('light').on('toggle', 'dark'),
state('dark').on('toggle', 'light'),
],
{ count: 0 },
{
onTransition: machine =>
machine.setContext(context => ({ count: context.count + 1 })),
}
)
return api(store).setExports({ send: store.send })
})
function Theme() {
const [{ context, value }, { send }] = useAtomState(themeAtom)
return (
Toggle Count: {context.count}
)
}
```
--------------------------------
### Garage Door State Machine Example (TypeScript/React)
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/walkthrough.mdx
A comprehensive example demonstrating a garage door state machine using Zedux. It utilizes `injectMachineStore` with `onEnter` to manage timeouts for 'opening' and 'closing' states, simulating door movement. The example also integrates with React using `useAtomValue` and `useAtomInstance` to display the current state and trigger transitions via a button.
```tsx
const doorAtom = atom('door', () => {
const store = injectMachineStore(
state => {
const startTimeout = machine => {
const { handle } = machine.getContext()
if (handle) clearTimeout(handle)
const newHandle = setTimeout(() => {
machine.setContext({ handle: null })
machine.send('timeout')
}, 1000)
machine.setContext({ handle: newHandle })
}
return [
state('open').on('click', 'closing'),
state('opening')
.on('click', 'closing')
.on('timeout', 'open')
.onEnter(startTimeout),
state('closed').on('click', 'opening'),
state('closing')
.on('click', 'opening')
.on('timeout', 'closed')
.onEnter(startTimeout),
]
},
{ handle: null }
)
return store
})
function Machine() {
const { value } = useAtomValue(doorAtom)
const { send } = useAtomInstance(doorAtom).store
return (
<>
State: {value}
>
)
}
```
--------------------------------
### config.onTransition Function Usage Example
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/injectMachineStore.mdx
An example showing how to use the `onTransition` function in the `injectMachineStore` config to perform actions or log information after a state transition.
```TypeScript
const store = injectMachineStore(statesFactory, initialContext, {
onTransition: (machineStore, storeEffect) => console.log(storeEffect)
})
```
--------------------------------
### Install Zedux Machines Package
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/overview.mdx
Provides commands to install the `@zedux/machines` package using npm, yarn, or pnpm. It highlights the peer dependency on `@zedux/atoms` or `@zedux/react`, ensuring correct versioning for Zedux applications.
```sh
npm install @zedux/atoms @zedux/machines # npm
yarn add @zedux/atoms @zedux/machines # yarn
pnpm add @zedux/atoms @zedux/machines # pnpm
```
```sh
npm install @zedux/react @zedux/machines # npm
yarn add @zedux/react @zedux/machines # yarn
pnpm add @zedux/react @zedux/machines # pnpm
```
--------------------------------
### Example: Basic useAtomInstance Usage and Context Provision
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/hooks/useAtomInstance.mdx
Provides additional examples of `useAtomInstance` usage, including passing parameters to an atom and demonstrating how an atom instance can be provided via React context using `AtomProvider`.
```tsx
const instance = useAtomInstance(myAtom)
const withParams = useAtomInstance(myAtom, ['param 1', 'param 2'])
// the instance can be provided over React context:
{children}
```
--------------------------------
### Comprehensive Todos Application with Zedux Atoms
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/quick-start.mdx
A full example demonstrating the use of Zedux atoms for a simple todos application. It defines `todosAtom` and `filteredTodosAtom` (a family atom using `injectAtomState`), and then uses `useAtomState` in React components to display filtered todos based on their completion status, showcasing atom composition and parameter usage.
```tsx
const todosAtom = atom('todos', () => [
{ text: 'Go', isDone: true },
{ text: 'Fight', isDone: true },
{ text: 'Win', isDone: false },
])
const filteredTodosAtom = atom('filteredTodos', (isDone: boolean) => {
const [todos] = injectAtomState(todosAtom)
const filteredTodos = todos.filter(todo => todo.isDone === isDone)
return filteredTodos.map(({ text }) => text)
})
// These 2 components pass different params to the filteredTodos atom:
function FinishedTodos() {
const [todos] = useAtomState(filteredTodosAtom, [true])
return
Finished Todos: {todos.join`, `}
}
function UnfinishedTodos() {
const [todos] = useAtomState(filteredTodosAtom, [false])
return
Unfinished Todos: {todos.join`, `}
}
const Todos = () => (
<>
>
)
```
--------------------------------
### Install @zedux/atoms and @zedux/machines
Source: https://github.com/omnistac/zedux/blob/master/packages/machines/README.md
Commands to install the `@zedux/atoms` and `@zedux/machines` packages using npm, yarn, or pnpm. `@zedux/atoms` is a peer dependency and should be installed at the same version.
```sh
npm install @zedux/atoms @zedux/machines # npm
```
```sh
yarn add @zedux/atoms @zedux/machines # yarn
```
```sh
pnpm add @zedux/atoms @zedux/machines # pnpm
```
--------------------------------
### Install @zedux/immer with npm, yarn, or pnpm
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/immer.mdx
Instructions for installing the `@zedux/immer` package along with its peer dependencies, `immer` and `@zedux/atoms`, using npm, yarn, or pnpm. It also notes an alternative installation for React applications where `@zedux/react` is used instead of `@zedux/atoms`.
```sh
npm install immer @zedux/atoms @zedux/immer # npm
yarn add immer @zedux/atoms @zedux/immer # yarn
pnpm add immer @zedux/atoms @zedux/immer # pnpm
```
```sh
npm install immer @zedux/react @zedux/immer # npm
yarn add immer @zedux/react @zedux/immer # yarn
pnpm add immer @zedux/react @zedux/immer # pnpm
```
--------------------------------
### Install @zedux/react package
Source: https://github.com/omnistac/zedux/blob/master/packages/react/README.md
Provides commands for installing the `@zedux/react` package using npm, yarn, or pnpm. This package is the primary entry point for using Zedux with React applications.
```sh
npm install @zedux/react
```
```sh
yarn add @zedux/react
```
```sh
pnpm add @zedux/react
```
--------------------------------
### ActionChain Example Implementations
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/types/ActionChain.mdx
Provides concrete TypeScript examples demonstrating different forms of `ActionChain` usage. This includes a basic `Action` acting as an `ActionChain`, an `ActionChain` representing an action inherited from a parent store, and one delegated to a specific child store.
```typescript
const justAnAction: ActionChain = {
type: 'todos/add',
payload: { text: 'be awesome' },
}
const fromParent: ActionChain = {
metaType: '@@zedux/inherit',
payload: {
type: 'todos/add',
payload: { text: 'be awesome' },
},
}
const fromChild: ActionChain = {
metaType: '@@zedux/delegate',
metaData: ['a', 'b'],
payload: {
type: 'todos/add',
payload: { text: 'be awesome' },
},
}
```
--------------------------------
### Install @zedux/immer for React Applications
Source: https://github.com/omnistac/zedux/blob/master/packages/immer/README.md
Instructions for installing `@zedux/immer` for React applications, where `@zedux/react` already includes `@zedux/atoms`.
```sh
npm install immer @zedux/react @zedux/immer
```
```sh
yarn add immer @zedux/react @zedux/immer
```
```sh
pnpm add immer @zedux/react @zedux/immer
```
--------------------------------
### statesFactory Return Value Example
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/injectMachineStore.mdx
An example showing how the `statesFactory` should return an array of `MachineState` objects, with the first state becoming the initial state of the machine.
```TypeScript
injectMachineStore(state => [state('initial'), state('other')])
```
--------------------------------
### createState Function Usage Examples
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/injectMachineStore.mdx
Examples demonstrating how to use the `createState` function (often aliased as `state` or `s`) within the `statesFactory` to define machine states.
```TypeScript
injectMachineStore(state => [state('a'), state('b')])
injectMachineStore(s => [s('a'), s('b')])
```
--------------------------------
### Set Up Zedux Documentation Site
Source: https://github.com/omnistac/zedux/blob/master/CONTRIBUTING.md
Instructions to set up and run the local development server for the Zedux documentation site, enabling hot module reloading (HMR) for quick previews.
```sh
cd docs
yarn
yarn start
```
--------------------------------
### Install @zedux/stores Package
Source: https://github.com/omnistac/zedux/blob/master/packages/stores/README.md
Instructions for installing the @zedux/stores package using common Node.js package managers like npm, yarn, or pnpm. This package is an addon for Zedux's composable store model.
```sh
npm install @zedux/stores # npm
yarn add @zedux/stores # yarn
pnpm add @zedux/stores # pnpm
```
--------------------------------
### Zedux Atom Getters: Dependency Tracking and Avoidance
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
This TypeScript example demonstrates how Zedux's ecosystem getter methods (`get`, `getNode`) now register dynamic and static dependencies respectively when called within reactive contexts. It also shows how to explicitly avoid dependency registration using `getOnce`, `getNodeOnce`, or by wrapping calls with `untrack`. This is a breaking change from v1 where these methods did not register dependencies.
```ts
import { Ecosystem, untrack } from '@zedux/react'
function maybeCalledReactively() {
return rootEcoSystem.get(myAtom)
}
// the ecosystem itself is now the first argument to selectors/ions:
function myExampleSelector((ecosystem: Ecosystem) => {
ecosystem.get(myAtom) // registers a dynamic dependency on myAtom
ecosystem.getNode(myAtom) // registers a static dependency on myAtom
ecosystem.getOnce(myAtom) // doesn't register anything
ecosystem.getNodeOnce(myAtom) // doesn't register anything
untrack(() => ecosystem.get(myAtom)) // doesn't register
let myAtomVal = maybeCalledReactively() // registers
myAtomVal = untrack(() => maybeCalledReactively()) // doesn't register
})
```
--------------------------------
### Install Zedux React Package
Source: https://github.com/omnistac/zedux/blob/master/README.md
This snippet demonstrates how to install the `@zedux/react` package using npm, yarn, or pnpm. This package includes the core atomic model and all React-specific APIs, and has a peer dependency on React 19+.
```bash
npm install @zedux/react # npm
yarn add @zedux/react # yarn
pnpm add @zedux/react # pnpm
```
--------------------------------
### Live Example: Providing, Consuming, and Subscribing to Atom State
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/react-context.mdx
A comprehensive live example demonstrating the full flow of providing an atom instance, consuming it in a child component, and subscribing to its state changes using `useAtomState`.
```tsx
const providedAtom = atom('provided', 'the state!')
function Child() {
const instance = useAtomContext(providedAtom)
const [state, setState] = useAtomState(instance) // subscribe to changes
return (
<>
Parent State (not subscribed): {instance.getState()}
)
}
```
--------------------------------
### Update Zedux Atom State in React Component
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/quick-start.mdx
This React (TSX) example demonstrates how to update the state of a Zedux atom instance. It uses `useAtomState()` to get the current atom state and a `setState` function. The `setState` function is then used in an `onChange` handler of an input field to dynamically modify the atom's value, triggering component rerenders. This showcases a complete interactive state management flow.
```tsx
const greetingAtom = atom('greeting', 'Hello, world!')
const Greeting = () => {
const [greeting, setGreeting] = useAtomState(greetingAtom)
return (
setGreeting(target.value)}
value={greeting}
/>
)
}
```
--------------------------------
### Zedux Atom Hydration Behavior Example
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
This example illustrates how Zedux automatically hydrates atoms immediately after initial evaluation, showing that explicit hydration logic for derived atoms might be redundant if source signals are hydrated.
```ts
// this atom behaves the same with or without these commented lines:
const hydratingAtom = atom('hydrating', () => {
const signalA = injectSignal('state a')
const signalB = injectSignal('state b')
// const hydration = injectHydration()
const composedSignal = injectMappedSignal({ a: signalA, b: signalB })
// composedSignal.set(hydration)
return composedSignal
})
```
--------------------------------
### Basic Zedux Store Usage Example
Source: https://github.com/omnistac/zedux/blob/master/packages/core/README.md
Demonstrates how to create a basic Zedux store using `createStore`, subscribe to state changes, retrieve the current state with `getState()`, and update the store's state using `setState()`. This example illustrates the fundamental interaction pattern with a Zedux store.
```tsx
import { createStore } from '@zedux/core'
// a zero-config store:
const store = createStore(null, 'Hello, World!')
const subscription = store.subscribe((newState, oldState) => {
console.log('store went from', oldState, 'to', newState)
})
store.getState() // 'Hello, World!'
store.setState('Goodbye, World!')
```
--------------------------------
### Get or Create Atom Instance
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/classes/Ecosystem.mdx
Shows how to use `rootEcosystem.getInstance()` to retrieve an atom instance, creating it if necessary. It also demonstrates basic interaction with the retrieved instance, like getting and setting state. This method does not register graph dependencies.
```TypeScript
const instance = rootEcosystem.getInstance(myAtom)
const withParams = rootEcosystem.getInstance(paramsAtom, ['param 1', 'param 2'])
instance.getState()
instance.setState('new state')
```
--------------------------------
### Diverse Configurations for injectStore
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/injectors/injectStore.mdx
This collection of examples demonstrates the versatility of `injectStore` by showing various initialization patterns. It covers scenarios like zero-configuration, manual store creation, custom reducer integration, store composition, disabling subscriptions, and handling hydration.
```ts
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())
)
```
--------------------------------
### Example: Getting a Selector Cache
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/selectors.mdx
Demonstrates how to use `ecosystem.selectors.getCache` to retrieve or create a selector cache for `getUserById` with a specific `userId`.
```ts
const cache = ecosystem.selectors.getCache(getUserById, [userId])
```
--------------------------------
### createReducer Usage Examples
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/factories/createReducer.mdx
Demonstrates various ways to use `createReducer` including setting initial state, handling string action types, multiple action types, and integrating with `actionFactory` for more complex action handling.
```typescript
import { actionFactory, createReducer } from '@zedux/react'
const withInitialState = createReducer('initial state')
const withoutInitialState = createReducer()
const withStringActionTypes = createReducer([]).reduce(
'todos/add',
(state, newTodo) => [...state, newTodo]
)
const multipleActions = createReducer([]).reduce(
['todos/reset', 'todos/clear'],
() => []
)
const addTodo = actionFactory('todos/add')
const removeTodo = actionFactory('todos/add')
const withActionFactories = createReducer([])
.reduce(addTodo, (state, newTodo) => [...state, newTodo])
.reduce(removeTodo, (state, id) => state.filter(todo => todo.id !== id))
const clear = actionFactory('todos/clear')
const mixed = createReducer([])
.reduce(addTodo, (state, newTodo) => [...state, newTodo])
.reduce('todos/remove', (state, id) => state.filter(todo => todo.id !== id))
.reduce(['todos/reset', clear], () => [])
```
--------------------------------
### Get Atom State Usage Examples
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/types/AtomGetters.mdx
Demonstrates various ways to use the `get` function to retrieve the current state of an atom instance's store. It accepts an atom template, a template with parameters, or an existing atom instance, creating the instance if it doesn't exist and registering a dynamic graph dependency.
```TypeScript
value = get(myAtom)
value = get(myAtom, [param1, param2])
value = get(myAtomInstance)
```
--------------------------------
### Full Example: Zedux State Machine with Context and onTransition Listener
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/walkthrough.mdx
A comprehensive example demonstrating a theme toggler using a Zedux state machine. It showcases context management to track toggle count and an `onTransition` listener to update the context automatically on state changes, providing a complete use case.
```tsx
const themeAtom = atom('theme', () => {
const store = injectMachineStore(
state => [
state('light').on('toggle', 'dark'),
state('dark').on('toggle', 'light'),
],
{ count: 0 },
{
onTransition: machine =>
machine.setContext(context => ({ count: context.count + 1 })),
}
)
// you can alias store methods on exports for use in `useAtomState`:
return api(store).setExports({ send: store.send })
})
function Theme() {
const [{ context, value }, { send }] = useAtomState(themeAtom)
return (
Toggle Count: {context.count}
)
}
```
--------------------------------
### Examples of `api` factory usage
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/factories/api.mdx
Illustrates various ways to use the `api` factory, including creating basic APIs, initializing with values or stores, adding/setting exports, handling promises, cloning existing APIs, and setting TTLs. Also shows an example of querying atoms.
```ts
import { api } from '@zedux/react'
const myApi = api()
const withValue = api('some value')
const withStore = api(injectStore())
const withExports = api(val).setExports({ ...myExports })
const withPromise = api(val).setPromise(myPromise)
const cloningApis = api(myApi).addExports(withExports.exports)
const addingExports = api(withExports).addExports({ ...moreExports })
const overwritingExports = api(withExports).setExports({ ...newExports })
const settingTtl = api().setTtl(0)
const ttlPromise = api().setTtl(myPromise)
const ttlObservable = api().setTtl(my$)
// query atoms:
return api(myPromise)
```
--------------------------------
### Complete Zedux Time Travel Plugin Example with Application Context
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/advanced/time-travel.mdx
This TSX example demonstrates the full integration of the Zedux time travel plugin within an application. It defines `undo` and `redo` actions using `actionFactory` and includes the complete plugin definition. The example also shows how an atom (`formAtom`) can be defined and how the `useEcosystem` hook might be used in a `Devtools` component, illustrating a practical setup for state management with time travel.
```tsx
const undo = actionFactory('@@timeTravel/undo')
const redo = actionFactory('@@timeTravel/redo')
const timeTravelPlugin = new ZeduxPlugin({
initialMods: ['stateChanged'],
registerEcosystem: ecosystem => {
const state = {
history: [],
isHydrating: false,
pointer: 0,
}
const subscription = ecosystem.modBus.subscribe({
effects: ({ action }) => {
// only track history if we're not currently time traveling
if (state.isHydrating) return
// only handle stateChanged mod events for atom instances
if (
action.type === ZeduxPlugin.actions.stateChanged.type &&
action.payload?.instance
) {
// get initial snapshot now
if (!state.history.length) {
const snapshot = ecosystem.dehydrate({
excludeFlags: ['no-time-travel'],
})
snapshot[action.payload.instance.id] = action.payload.oldState
state.history.push(snapshot)
}
state.history = [
...state.history.slice(0, state.pointer + 1),
ecosystem.dehydrate({ excludeFlags: ['no-time-travel'] }),
]
state.pointer += 1
return
}
if (action.type === undo.type) {
const { pointer } = state
const newPointer = Math.max(0, pointer - 1)
if (newPointer === pointer) return
state.pointer = newPointer
state.isHydrating = true
ecosystem.hydrate(state.history[newPointer])
state.isHydrating = false
return
}
if (action.type === redo.type) {
const { history, pointer } = state
const newPointer = Math.min(history.length - 1, pointer + 1)
if (newPointer === pointer) return
state.pointer = newPointer
state.isHydrating = true
ecosystem.hydrate(state.history[newPointer])
state.isHydrating = false
return
}
},
})
return () => subscription.unsubscribe()
},
})
const formAtom = atom('form', () => {
const store = injectStore({
email: '',
password: '',
})
return api(store).setExports({
setEmail: email => store.setStateDeep({ email }),
setPassword: password => store.setStateDeep({ password }),
})
})
function Devtools() {
const ecosystem = useEcosystem()
return (
```
--------------------------------
### Example of Atom Hydration with Transformation
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/advanced/persistence.mdx
Illustrates a complete hydration flow where an atom's state is hydrated using `injectStore({ hydrate: true })` and then transformed by a function provided in the atom's `hydrate` config option. This example shows how to set up an ecosystem and hydrate it with initial data.
```typescript
const myAtom = atom(
'myKey',
() => {
return injectStore('default', { hydrate: true })
},
{ hydrate: hydration => `${hydration} and transformed!` }
)
const ecosystem = createEcosystem({ id: 'hydrate-flow-example' })
ecosystem.hydrate({ myKey: 'hydrated' })
const output = ecosystem.get(myAtom)
```
--------------------------------
### Cross-Window Zedux Internals Sharing Example
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
This TypeScript example illustrates how to share Zedux's internal state between different browser windows (e.g., parent and child). It demonstrates using `getInternals` from `@zedux/react` and `getStoreInternals` from `@zedux/stores` in a parent window, and then `setInternals` and `setStoreInternals` in a child window to establish shared state.
```ts
// an example parent-child setup
// parent window:
import { getInternals } from '@zedux/react'
import { getStoreInternals } from '@zedux/stores'
window.zeduxInternals = getInternals()
window.zeduxStoreInternals = getStoreInternals()
// child window:
import { setInternals } from '@zedux/react'
import { setStoreInternals } from '@zedux/stores'
setInternals(window.opener.zeduxInternals)
setStoreInternals(window.opener.zeduxStoreInternals)
```
--------------------------------
### Create a Basic Zedux State Machine
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/packages/machines/walkthrough.mdx
Demonstrates how to initialize a state machine using `injectMachineStore()`. The first state defined in the array becomes the initial state of the machine.
```TypeScript
import { injectMachineStore } from '@zedux/machines'
import { atom } from '@zedux/react'
const trafficLightAtom = atom('trafficLight', () => {
const store = injectMachineStore(state => [
state('green'), // <- the initial state
state('yellow'),
state('red')
])
return store
})
```
--------------------------------
### Zedux Atom State Factory for Initial State
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/quick-start.mdx
Illustrates the basic usage of a factory function as the second argument to `atom()`. This function is responsible for creating and returning the initial state of the atom instance.
```ts
const helloAtom = atom('hello', () => 'world')
```
--------------------------------
### Basic Zedux Ecosystem and Atom Instance Usage
Source: https://github.com/omnistac/zedux/blob/master/docs/blog/2023-04-24-zedux-is-this-the-one.md
Demonstrates the fundamental usage of a Zedux Ecosystem and how to interact with an atom instance. It shows creating an ecosystem, retrieving an atom's instance, accessing its state, subscribing to state changes, and updating the atom's state.
```ts
const ecosystem = createEcosystem({ id: 'root' })
const instance = ecosystem.getInstance(counterAtom)
instance.getState()
instance.store.subscribe(newState => console.log('state changed:', newState))
instance.setState(100)
```
--------------------------------
### Get Atom Value
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/atom-getters.mdx
Returns the current value of an atom instance. This function creates the instance using the passed template if it doesn't already exist. Examples show usage both without and with parameters for the atom.
```ts
const value = get(myAtom)
// or, if the atom takes params:
get(myAtom, ['param 1', 'param 2'])
```
--------------------------------
### Create a Basic Signal with Zedux Ecosystem
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
Illustrates the basic creation of a signal using `ecosystem.signal`, demonstrating that signals can be created independently of atoms.
```ts
const signal = ecosystem.signal('some state')
```
--------------------------------
### Get Atom Instance in React with useAtomInstance
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/quick-start.mdx
Demonstrates how to obtain an `AtomInstance` in a React component using the `useAtomInstance` hook. This hook does not subscribe to state updates, making it suitable for preventing unnecessary re-renders when only the instance itself is needed.
```ts
function MyComponent() {
const instance = useAtomInstance(myAtomTemplate)
...
}
```
--------------------------------
### Ecosystem.onReady Method API Reference
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/classes/Ecosystem.mdx
Detailed API documentation for the `Ecosystem.onReady` method, including its purpose, parameters (`ecosystem`, `prevContext`), and return type. This method is crucial for bootstrapping and re-initializing ecosystem data.
```APIDOC
Ecosystem.onReady(ecosystem: Ecosystem, prevContext?: any) => Function | undefined
Description: A function. May be undefined. This is set to the onReady value you passed via EcosystemConfig when creating this ecosystem. Will be called as soon as the ecosystem has initialized. Is also called every time the ecosystem is reset. This is the ideal place to bootstrap data and preload atoms. Since this function is called on reset, it can be used to ensure the ecosystem's "necessary data" is always loaded.
Parameters:
ecosystem: Ecosystem
Description: A reference to this ecosystem.
prevContext: any (optional)
Description: A reference to the previous context value of the ecosystem. ecosystem.reset() can be optionally given a new context object. If that happens, the ecosystem's context will be updated before this function is called. So a reference to the old context is passed here. This parameter will be undefined the first time onReady runs. Thus you can use this to check if this is the initial run.
Returns: Function | undefined
Description: Either undefined or a cleanup function that will be called when the ecosystem is reset or destroyed.
```
--------------------------------
### Get Atom Instance
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/walkthrough/atom-getters.mdx
Returns an atom instance, creating it using the provided template if it doesn't exist. This method provides direct access to the atom instance itself, rather than its value. Examples demonstrate how to call it with and without parameters.
```ts
const instance = getInstance(myAtom)
// or, if the atom takes params:
getInstance(myAtom, ['param 1', 'param 2'])
```
--------------------------------
### Ecosystem.onReady Usage Example: Initial Run and Reset Handling (TypeScript)
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/classes/Ecosystem.mdx
Illustrates how to implement the `onReady` callback to differentiate between the initial ecosystem run and subsequent calls after a reset. It demonstrates checking `prevContext` to determine the execution context and reacting to changes in the ecosystem's context.
```TypeScript
const ecosystem = createEcosystem({
context: { redux: reduxStore },
onReady: (ecosystem, prevContext) => {
if (!prevContext) {
// this is the initial run
} else {
// onReady is running after an ecosystem reset
const nextContext = ecosystem.context
if (prevContext.redux !== nextContext.redux) {
// ecosystem.reset() changed the redux store reference
}
}
}
})
ecosystem.reset() // doesn't change context (prevContext === ecosystem.context)
ecosystem.reset({ redux: otherReduxStore }) // replaces context
```
--------------------------------
### injectEffect Order Change Example
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
This TypeScript example illustrates a breaking change in `injectEffect`'s execution order. In Zedux v1, the `console.log` would output "1" due to deferred effect execution; in v2, it outputs "0" because effects now run immediately when safe. This change impacts timing-sensitive code and may require explicit dependency declaration or asynchronous handling.
```ts
const exampleAtom = atom('example', () => {
const store = injectStore(0)
injectEffect(() => {
console.log(store.getState()) // "1" in v1, "0" in v2
}, []) // adding `store.getState()` as a dep would fix this in v2
return store
})
const exampleInstance = ecosystem.getInstance(exampleAtom)
exampleInstance.setState(1)
```
--------------------------------
### Replacing Zedux Stores with Signals
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/migrations/v2.mdx
This snippet illustrates the core migration from Zedux stores to signals, showing how to replace `injectStore` with `injectSignal` and update method calls like `getState` to `get`, `setState` to `set`, and `setStateDeep` to `mutate`.
```ts
// before:
import { storeApi as api, storeAtom as atom, injectStore } from '@zedux/stores'
```
```ts
// after:
import { api, atom, injectSignal } from '@zedux/react'
// replace `injectStore` with `injectSignal`
// replace `store.getState` with `signal.get`
// replace `store.setState` with `signal.set`
// replace `store.setStateDeep` with `signal.mutate`
```
--------------------------------
### Basic Usage of injectWhy to Get Evaluation Reasons
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/injectors/injectWhy.mdx
Provides a simple example of using `injectWhy` to retrieve and display the list of evaluation reasons for an atom. It sets up an interval to trigger state changes, allowing observation of how the reasons are updated over time.
```tsx
const reasonsAtom = atom('reasons', () => {
const store = injectStore(0)
injectEffect(() => {
const intervalId = setInterval(() => store.setState(val => val + 1), 1000)
return () => clearInterval(intervalId)
}, [])
const reasons = injectWhy()
return reasons
})
function Reasons() {
const reasons = useAtomValue(reasonsAtom)
return (
<>
Last Evaluation Reasons:
{JSON.stringify(reasons, null, 2)}
>
)
}
```
--------------------------------
### Start Local Docusaurus 2 Development Server
Source: https://github.com/omnistac/zedux/blob/master/docs/README.md
This command initiates a local development server for the Docusaurus 2 website and automatically opens a browser window. It supports live reloading, reflecting most changes without requiring a server restart.
```shell
$ yarn start
```
--------------------------------
### Zedux: Implementing a Filtered List with AtomSelector
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/about/recoil-comparison.mdx
This example shows how Zedux achieves derived state similar to Recoil's selectors using an `AtomSelector`. It demonstrates accessing other atom values via the `get` function within the selector.
```tsx
const getFilteredTodoList = ({ get }: AtomGetters) => {
const filter = get(todoListFilterAtom)
const list = get(todoListAtom)
switch (filter) {
case 'Show Completed':
return list.filter(item => item.isComplete)
case 'Show Uncompleted':
return list.filter(item => !item.isComplete)
default:
return list
}
}
```
--------------------------------
### Examples of createStore Usage
Source: https://github.com/omnistac/zedux/blob/master/docs/docs/api/factories/createStore.mdx
Demonstrates various ways to use `createStore` to initialize different types of Zedux stores, including zero-config, stores with initial state, reducer-based, state machine, and deeply composed stores.
```ts
import { createStore } from '@zedux/react'
const zeroConfigStore = createStore()
zeroConfigStore.setState('initial state')
const zeroConfigStoreWithInitialState = createStore(null, 'initial state')
zeroConfigStoreWithInitialState.setState('new state')
const reducerStore = createStore(myRootReducer)
reducerStore.dispatch({ type: 'my-action-type' })
const machineStore = createStore(stateMachine)
machineStore.dispatch({ type: 'my-action-type' })
const composedStore = createStore({
zeroConfig: zeroConfigStore,
reducerStore: reducerStore,
machineStore: machineStore
})
const bigComposedStore = createStore({
a: storeA,
b: reducerB,
c: {
d: reducerD,
e: storeE,
f: {
g: storeG
}
}
})
```