Reading state
Olik supports synchonous reads and the ability to listen for updates to a node​
Let's begin with the following store:
import { createStore } from 'olik'
const store = createStore({
name: document.title,
state: {
todos: new Array<{ id: number, title: string, done: boolean }>(),
showDone: false,
}
});
Reading synchronously​
To read state associated with a node, you can use the $state
property.
The following statements are equivalent to each other:
const todos = store.todos.$state;
const todos = store.$state.todos;
Reacting to state changes​
store.todos
.$onChange(todos => /* Update DOM */)
sub.unsubscribe()
// Remember to **always** unsubscribe to avoid a memory leak
export function App() {
const todos = store.todos.$useState();
return (/* rendered content */);
}
<div *ngFor="let todo of todos$ | async">
{{todo.title}}
</div>
@Component({...})
export class MyComponent {
todos$ = store.todos.$observe();
}
Consuming observables more easily​
The combineComponentObservables()
is a convenience function that dramatically reduces the number of async
pipes in your template and allows you to read your component observables, synchronously, without subscribing to them.
<ng-container *ngIf="obs$ | async; let obs;">
<div>Todos for user: {{obs.username$}}</div>
<div *ngFor="let todo of obs.todos$"> {{todo.title}} </div>
</ng-container>
import { combineComponentObservables } from 'olik-ng';
@Component({...})
export class AppComponent implements AfterViewInit {
username$ = store.username.$observe()
todos$ = store.todos.$observe()
obs$ = combineComponentObservables<AppComponent>(this)
// NOTE: the above obs$ variable must NOT be renamed and
// must be declared AFTER all other observables
ngAfterViewInit() {
console.log({ todos: this.obs$.todos$ }) // synchronous read
}
}
{#each $store.todos as todo}
<li> {todo.title} </li>
{/each}
or
const todos = store.todos.$observe();
{#each $todos as todo}
<li> {todo.title} </li>
{/each}
Deriving computationally expensive state​
import { derive } from 'olik'
const sub = derive(store.todos, store.showDone)
.$with((todos, showDone) => todos.filter(todo => todo.done === showDone))
.$onChange(todos => /* Update DOM */)
sub.unsubscribe()
// Remember to **always** unsubscribe to avoid a memory leak
import { derive } from 'olik'
export function MyComponent() {
const todos = derive(store.todos, store.showDone)
.$with((todos, showDone) => todos.filter(todo => todo.done === showDone))
.$useState()
return (/* rendered content */);
}
import { derive } from 'olik'
@Component({...})
export class MyComponent {
completedTodos$ = derive(store.todos, store.showDone)
.$with((todos, showDone) => todos.filter(todo => todo.done === showDone))
.$observe()
}
import { derive } from 'olik'
const completedTodos = derive(store.todos, store.showDone)
.$with((todos, showDone) => todos.filter(todo => todo.done === showDone))
.$observe()