add createService (#6)

This commit is contained in:
Kilin Mikhail
2020-12-26 00:20:01 +03:00
committed by GitHub
parent fd79931b16
commit 6d605cd325
4 changed files with 63 additions and 6 deletions

View File

@ -1,9 +1,7 @@
import {format} from 'date-fns';
import {parse} from 'querystring';
import React, {memo} from 'react'; import React, {memo} from 'react';
import {numberParser, QueryParsers, stringParser, useQuery} from '../../../../common/hooks/useQuery'; import {numberParser, QueryParsers, stringParser, useQuery} from '../../../../common/hooks/useQuery';
import {QueryResponse, QueryResponseError} from '../../types';
// eslint-disable-next-line
const enum PersonType { const enum PersonType {
One = 'one', One = 'one',
Two = 'two' Two = 'two'
@ -24,7 +22,7 @@ const parsers: QueryParsers<Person> = {
const AuthResponsePage: React.FC = () => { const AuthResponsePage: React.FC = () => {
const query = useQuery(parsers); const query = useQuery(parsers);
return ( return (
<div>Auth Page</div> <div>Auth Page {query.name}</div>
); );
}; };

View File

@ -2,16 +2,39 @@ import React, {memo} from 'react';
import {AuthService} from '../../../../services/AuthService'; import {AuthService} from '../../../../services/AuthService';
import {useStream} from '../../../../utils/useStream'; import {useStream} from '../../../../utils/useStream';
import ComponentStream from '../component-stream/ComponentStream'; import ComponentStream from '../component-stream/ComponentStream';
import {createService} from '../../../../utils/createService';
const service = createService(1, {
changeWithStr: (state: number, val: string) => {
const parsedNumber = Number(val);
if (Number.isNaN(val)) {
return state;
}
return parsedNumber;
},
add: (state: number) => {
return state + 1;
},
sub: (state: number) => {
return state - 1;
}
});
const MainPage: React.FC = () => { const MainPage: React.FC = () => {
const {isAuth} = useStream(AuthService.state$, AuthService.initState); const {isAuth} = useStream(AuthService.state$, AuthService.initState);
const toggle = () => AuthService.handleChangeAuth(!isAuth); const toggle = () => AuthService.handleChangeAuth(!isAuth);
const data = useStream(service.stream$, 0);
return ( return (
<div> <div>
Main Page Main Page
Auth: {isAuth ? 'yes' : 'no'} Auth: {isAuth ? 'yes' : 'no'}
<button onClick={toggle}>click</button> <button onClick={toggle}>click</button>
<ComponentStream /> <ComponentStream />
<div>{data}</div>
<button onClick={service.actions.add}>Add</button>
<button onClick={service.actions.sub}>Sub</button>
</div> </div>
); );
}; };

View File

@ -0,0 +1,36 @@
import {startWith} from '@most/core';
import {createAdapter} from '@most/adapter';
import {pipe} from 'fp-ts/es6/pipeable';
type ServiceAction<State, ValType> = (data: State, val?: ValType) => State;
type ServiceActions<State, T extends Record<string, ServiceAction<State, unknown>>> = {
[Key in keyof T]: T[Key] extends ServiceAction<State, infer D>
? D extends void | undefined
? () => State
: (val: D) => State
: never;
};
// eslint-disable-next-line
export const createService = <State, Actions extends Record<string, ServiceAction<State, any>>>(
initData: State,
actions: Actions
) => {
const [handler, adapterStream$] = createAdapter<State>();
let currValue = initData;
const currStream$ = pipe(adapterStream$, startWith(initData));
const currActions = Object.entries(actions).reduce((acc, [key, func]) => {
// eslint-disable-next-line
(acc as any)[key] = (val: unknown) => {
currValue = func(currValue, val);
handler(currValue);
};
return acc;
}, {} as ServiceActions<State, Actions>);
return {
stream$: currStream$,
actions: currActions,
initialState: initData
};
};

View File

@ -3,7 +3,7 @@ import {Stream, Sink} from '@most/types';
import {newDefaultScheduler} from '@most/scheduler'; import {newDefaultScheduler} from '@most/scheduler';
import {pending, RemoteData} from '@devexperts/remote-data-ts'; import {pending, RemoteData} from '@devexperts/remote-data-ts';
// eslint-disable-next-line no-empty-function // eslint-disable-next-line
const emptyFunc = () => {}; const emptyFunc = () => {};
export const useStream = <T>(stream$: Stream<T>, defaultValue: T): T => { export const useStream = <T>(stream$: Stream<T>, defaultValue: T): T => {
@ -22,7 +22,7 @@ export const useStream = <T>(stream$: Stream<T>, defaultValue: T): T => {
return () => { return () => {
effect$.dispose(); effect$.dispose();
}; };
}, []); }, [stream$]);
return state; return state;
}; };