What's new
State plugin hooks - #20
With [email protected], the core system will now support some initialization hooks
under the hood:
- onInit: it runs when your store state initialises, after all given plugins have been applied.
- onDestroy: it runs when the reactive owner is disposed.
You can access these hooks while creating a plugin or while defining a store extension through the .extend()
method. Hooks are basically registered callbacks in a queue system and they will be applied in order.
const myPlugin = makePlugin((state, context) => {
context.hooks.onInit(() => console.log('run on state init'));
context.hooks.onDestroy(() => console.log('run on state destroy'));
}, { name: 'myPlugin' });
createRoot(dispose => {
const container = Container.create();
const CountState = defineSignal(() => 0)
.extend(myPlugin);
const count = container.get(CountState);
// ✅ onInit hook will run
container.get(CountState);
// ❌ onInit hook will not run anymore: state is already initialised
dispose();
// ✅ onDestroy hook will run
})
State support for solid-js createResource
- #22
This new version add support for creating StateBuilders state definitions using solid-js createResource
under the hood. It's now marked as experimental feature.
The state built with this new api will return basically a Resource which uses the mutate
function under the hood as store setter
. It acts like a wrapper but with the support of StateBuilder plugin extension and hook system.
import { experimental__defineResource } from 'statebuilder';
const TodoAsyncState = experimental__defineResource(
() => fetch('https://jsonplaceholder.typicode.com/todos/1').then(response => response.json())
).extend(() => {
// ...
});
const todoState = container.get(TodoAsyncState);
// ˆ? todoState: Resource<Todo> & { set: Setter<Todo>, refetch(init?: unknown): void }
statebuilder/commands drop support for RxJS - #17
Since this version, the command
plugin will not use anymore RxJS to handle the command event state. Instead, it will use directly the solid-js signal based system.
Since Solid handle signals like RxJS BehaviorSubject
, and the previous implementation had an attached Subject
under the hood, the code for watching the commands events should change.
Since the watchCommand
method will now return an Accessor<Command>
instead of a BehaviorSubject
, In order to avoid to run the callback before receiving your watched commands, you can mix the createEffect
with the on
utility.
Before:
interface Commands {
add: number;
}
const CountStore = defineSignal(() => 0)
.extend(withProxyCommands<Commands>())
.extend(state => {
const watch$ = state.watchCommand([state.commands.add]);
// ˆ? watch$: Observable<StateCommand<'add', number>>
watch$.subscribe((x) => console.log(x))
})
After:
import {createEffect, on} from 'solid-js';
interface Commands {
add: number;
}
const CountStore = defineSignal(() => 0)
.extend(withProxyCommands<Commands>())
.extend(state => {
const watched = state.watchCommand([state.commands.add]);
// ˆ? watched: Accessor<StateCommand<'add', number>>
createEffect(on(watched, command => {
console.log(command);
}))
})
What's Changed
- perf: refactor commands plugin removing RxJS by @riccardoperra in #17
- feat: add store definition init/destroy hooks. support local owner by @riccardoperra in #20
- test: hooks by @riccardoperra in #21
- feat: command devtools by @riccardoperra in #19
- feat: store resource by @riccardoperra in #22
- chore: update versions by @github-actions in #18
Full Changelog: https://github.com/riccardoperra/statebuilder/compare/[email protected]@0.4.0