Skip to content

Sources

Your source owns state and behavior.

Pass it to igniteCore through the entrypoint for your source library.

Use states to derive values for the view and commands to call the source.

An Ignite source adapter connects your source to Ignite’s observation and command APIs.

SourceImport igniteCore from
XStateignite-element/xstate
Reduxignite-element/redux
MobXignite-element/mobx

Network requests, storage, timers, and other I/O stay in your source or application.

Choose the input that creates a new source for each element:

Source libraryInput to igniteCoreWhat each element gets
XStatesource: toggleMachineA new actor created from the machine definition
Reduxsource: sliceA new store created from the slice
MobXsource: () => new Counter()A new observable returned by the function

The MobX function must create a new observable each time it is called.

For shared state, pass the existing observable directly instead of returning a singleton from a factory.

The complete modules below export a core with derived state and commands.

Definitions and fresh factories also provide a private runtime per useIgnite(core) call. Existing actor, store or observable instances share state instead.

Use that core to register a view, as shown in Getting started.

The callback input depends on the source adapter.

SourceInput to states
XStateThe actor snapshot, including context, matches(...), and can(...) for state machines.
ReduxThe store’s getState() result, or the selected slice state when you pass a slice.
MobXThe result of toJS(store), rather than the observable instance itself.

The name snapshot in the examples is a callback parameter, not a shared shape across all sources.

The configuration’s source tells Ignite what to create or observe.

Inside commands: ({ source }), source provides commands for the active actor or store.

For a machine, slice, or factory, the callback receives the created instance’s command interface.

The examples use { source: store } to name that callback value store.

Install Ignite and XState:

Terminal
pnpm add ignite-element@beta xstate

The Getting started light switch passes a machine definition to igniteCore.

Each mounted light switch gets its own actor.

For shared state, pass an existing started actor; see Shared XState source.

XState machine states describe behavior; Ignite’s states callback derives values for views.

Keep guards, invoked services, cancellation, retries, and persistence in XState or the application.

Install Ignite and Redux Toolkit:

Terminal
pnpm add ignite-element@beta @reduxjs/toolkit

Save this complete module as redux-slice.ts:

redux-slice.ts
import { createSlice } from "@reduxjs/toolkit";
import { igniteCore } from "ignite-element/redux";
const slice = createSlice({
name: "counter",
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
},
});
export const core = igniteCore({
source: slice,
states: (snapshot) => ({ count: snapshot.count }),
commands: ({ source: store }) => ({
increment: () => store.dispatch(slice.actions.increment()),
}),
});

Pass the slice itself as source.

Ignite creates a separate store for each element using this core.

The states callback receives the slice state, so the count is snapshot.count.

The increment() command dispatches the slice’s action to the store.

Configure your own store

Use a store factory when you need custom middleware or combined reducers.

The factory must create a new store each time it is called.

Independent hook construction, including factory middleware/enhancers, must be safe to repeat and discard without cleanup; see ownership.

Save this alternative module as redux-factory.ts:

redux-factory.ts
import { configureStore, createSlice } from "@reduxjs/toolkit";
import { igniteCore } from "ignite-element/redux";
const slice = createSlice({
name: "counter",
initialState: { count: 0 },
reducers: {
increment: (state) => {
state.count += 1;
},
},
});
export const core = igniteCore({
source: () => configureStore({ reducer: slice.reducer }),
states: (snapshot) => ({ count: snapshot.count }),
commands: ({ source: store }) => ({
increment: () => store.dispatch(slice.actions.increment()),
}),
});

Here states receives the store’s full state.

For a combined reducer, read its root shape, such as snapshot.counter.count.

For shared state, pass an existing store; see Shared Redux store.

Install Ignite and MobX:

Terminal
pnpm add ignite-element@beta mobx

Save this complete module as mobx-factory.ts:

mobx-factory.ts
import { igniteCore } from "ignite-element/mobx";
import { makeAutoObservable } from "mobx";
class Counter {
count = 0;
constructor() {
makeAutoObservable(this);
}
increment() {
this.count += 1;
}
}
export const core = igniteCore({
source: () => new Counter(),
states: (snapshot) => ({ count: snapshot.count }),
commands: ({ source: store }) => ({ increment: () => store.increment() }),
});

makeAutoObservable(this) makes each Counter instance observable.

source: () => new Counter() lets Ignite create a new instance for each element, or each hook.

Existing instances remain shared.

Independent views release their runtime automatically; call core.dispose() when the core’s owner ends.

Incrementing one element changes only that element’s counter.

The states callback reads the observable data copied by toJS.

Use that snapshot for data fields such as count.

Call actions on the observable received by commands, rather than on the snapshot.

The increment() command calls store.increment() on the observable instance.

For shared state, pass an existing observable; see Shared MobX observable.

  • Shared sources: share state between views and own its lifetime.
  • Routing: connect navigation to source behavior.

Find these pages again in the sidebar’s Guides group.

  • Views: render the values and commands exposed by your core.
  • Ownership & cleanup: choose shared or isolated state and place cleanup at its owner boundary.

When the owning feature or session permanently discards a core, call core.dispose().

An external source stays under its owner’s control until nothing else needs it.