Observable
![Code style](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)
Linked projects
name | version | downloads |
---|
observable-form | ![npm version](https://badge.fury.io/js/%40muzikanto%2Fobservable-form.svg) | ![downloads](https://img.shields.io/npm/dm/@muzikanto/observable-form.svg) |
Introduction
- create store
- listen store changes
- listen store object part change
- create event and subscribe store to event
- create effect and subscribe events (done, fail, loading)
- create cacheable effect
- async store parts with combineAsync
- override Event, Effect, Store if you need
- and more..
Installation
npm i @muzikanto/observable
yarn add @muzikanto/observable
Migrate 3.x.x > 4.x.x
remove to @muzikanto/observable-global
- createGlobalStore
- GlobalStoreCtx
- GlobalStoreProvider
- useGlobal
Examples
More examples
example createStore
const store = createStore<number>({ value: 1 });
function Component() {
const state = useStore(store);
return <span>{state.value}</span>;
}
example createEvent
const store = createStore<number>(1);
const append = createEvent<number>();
const change = createEvent<number>();
store.on(append, (state, payload) => state + payload);
store.on(change, (state, payload) => payload);
append(2);
change(-2);
store.reset();
Run in CodeBox
example createEffect
type Request = { param: number };
const effect = createEffect<Request, Response, Error>(
async (params: Request) => {
try {
const response = await axios.get('https://example.com', { params });
return response;
} catch (e) {
throw e;
}
},
{ cache: true, cacheTime: 60000 },
);
storeDone.on(effect.done, (_, payload) => payload);
storeFail.on(effect.fail, (_, payload) => payload);
storeLoading.on(effect.loading, (_, payload) => payload);
effect({ param: 1 })
.then((response) => console.log(response))
.catch((err) => console.log(err));
example combine
const one = createStore('Hello ');
const two = createStore('World');
const combinedObjStore = combine({ one, two });
combinedObjStore.get();
const combinedStringStore = combine({ one, two }, ({ one, two }) => {
return one + ' ' + two;
});
combinedStringStore.get();
example combineAsync
const one = createStore(1);
const two = createStore(2);
const three = createStore(3);
const combinedStore = combineAsync({ one, two });
combinedStore.get();
combinedStore.injectStore('three', three);
combinedStringStore.get();
example timer
(async () => {
const store = createStore(1);
const ev = createEvent<number>();
store.on(ev, (state, payload) => state + payload);
const runTimer = timer(ev, 200);
runTimer(2);
await wait(200);
store.get();
})()(
async () => {
const store = createStore(1);
const ev = createEvent<number>();
store.on(ev, (state, payload) => state + payload);
const runTimer = timer(ev, 200, 100);
runTimer(2);
await wait(200);
await wait(100);
await wait(100);
store.get();
},
)();
Api
createStore
function createStore<T>(initialState: T): Store<T>
interface Store<T> {
get: () => T;
set: (v: T) => void;
subscribe: (listener: Listener<any>, selector?: (state: T) => any) =>() => void;
reset: () => void;
on: <P>(event: IEvent<P>, handler: (state: T, payload: P) => T) => () => void;
watch: (handler: (state: T, prev: T) => void): () => void;
}
createEvent
function createEvent<P = void>(): IEvent<P>;
type IEvent<P = void> = {
(payload: P): void;
watch: (watcher: Listener<P>) => () => void;
};
createEffect
function createEffect<Req, Res, Err = Error>(
handler: (params: Req) => Promise<Res>,
options?: {
done?: IEvent<Res>;
fail?: IEvent<Err>;
loading?: IEvent<boolean>;
cache?: boolean;
cacheTime?: number;
},
): IEffect<Req, Res, Err>;
type IEffect<Req, Res, Err = Error> = {
(request: Req): Promise<Res>;
done: IEvent<Res>;
fail: IEvent<Err>;
loading: IEvent<boolean>;
};
createApi
function createApi<S, A extends { [key: string]: (state: S, payload: any) => S }>(
state: S,
api: A,
): Api<S, A>;
type Api<S, A extends { [key: string]: (store: Store<S>, payload: any) => S }> = ApiEvents<S, A> & {
store: Store<S>;
};
type ApiEvents<S, A> = {
[K in keyof A]: A[K] extends (store: S, e: infer E) => S ? IEvent<E> : any;
};
combine
function combine<Map extends { [key: string]: any }, S = Map>(
map: { [k in keyof Map]: Store<Map[k]> },
func?: (map: Map) => S,
): CombineStore<S>;
combineAsync
function combineAsync<Map extends { [key: string]: any }, S = Map>(
map: { [k in keyof Map]: Store<Map[k]> },
func?: (map: Map) => S,
): CombineAsyncStore<S>;
forward
function forward<P>(
from: IEvent<P>,
to: IEvent<P> | Array<IEvent<P>>,
): (() => void) | Array<() => void>;
timer
export type Timer<R> = IEvent<R> & {
disable: () => void;
};
function timer<R>(event: IEvent<R>, timeout: number, interval?: number): Timer<R>;
useStore
function useStore<T, V>(observable: Store<T>, selector?: (state: T) => V): V;
License
MIT