Skip to content
Snippets Groups Projects
Commit bfe943bc authored by Loïc Correnson's avatar Loïc Correnson
Browse files

[dome] Local & Global states

parent a75b4445
No related branches found
No related tags found
No related merge requests found
......@@ -17,8 +17,49 @@ import * as JSON from './json';
const UPDATE = 'dome.states.update';
/** State interface. */
export type State<A> = [A, (update: A) => void];
/** State field of an object state. */
export function key<A, K extends keyof A>(
state: State<A>,
key: K,
): State<A[K]> {
const [props, setProps] = state;
return [props[key], (value: A[K]) => {
const newProps = Object.assign({}, props);
newProps[key] = value;
setProps(newProps);
}];
}
/** State index of an array state. */
export function index<A>(
state: State<A[]>,
index: number,
): State<A> {
const [array, setArray] = state;
return [array[index], (value: A) => {
const newArray = array.slice();
newArray[index] = value;
setArray(newArray);
}];
}
/** Log state updates in the console. */
export function debug<A>(msg: string, st: State<A>): State<A> {
const [value, setValue] = st;
return [value, (v) => { console.log(msg, v); setValue(v); }];
}
/** Purely local value. No hook, no events, just a ref. */
export function local<A>(init: A): State<A> {
const ref = { current: init };
return [ref.current, (v) => ref.current = v];
}
/** Cross-component State. */
export class State<A> {
export class GlobalState<A> {
private value: A;
private emitter: Emitter;
......@@ -53,8 +94,10 @@ export class State<A> {
}
/** React Hook, similar to `React.useState()`. */
export function useState<A>(s: State<A>): [A, (update: A) => void] {
/** React Hook, similar to `React.useState()`.
Assignments to the global state also update _all_
its associated hooks and listeners. */
export function useGlobalState<A>(s: GlobalState<A>): State<A> {
const [current, setCurrent] = React.useState<A>(s.getValue);
React.useEffect(() => {
s.on(setCurrent);
......
......@@ -13,7 +13,7 @@ import React from 'react';
import * as Dome from 'dome';
import * as Json from 'dome/data/json';
import { Order } from 'dome/data/compare';
import * as GlobalStates from 'dome/data/states';
import { GlobalState, useGlobalState } from 'dome/data/states';
import { useModel } from 'dome/table/models';
import { CompactModel } from 'dome/table/arrays';
import * as Server from './server';
......@@ -534,7 +534,7 @@ function reducer(s: Selection, action: SelectionActions): Selection {
}
}
const GlobalSelection = new GlobalStates.State<Selection>({
const GlobalSelection = new GlobalState<Selection>({
current: undefined,
prevSelections: [],
nextSelections: [],
......@@ -544,7 +544,7 @@ const GlobalSelection = new GlobalStates.State<Selection>({
Current selection.
*/
export function useSelection(): [Selection, (a: SelectionActions) => void] {
const [selection, setSelection] = GlobalStates.useState(GlobalSelection);
const [selection, setSelection] = useGlobalState(GlobalSelection);
function update(action: SelectionActions) {
const nextSelection = reducer(selection, action);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment