Created
June 18, 2021 08:28
-
-
Save InfiniteXyy/eac1aa80ff99a7a3235ec27d0d15254d to your computer and use it in GitHub Desktop.
use factory api for ayanami
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@asuka/di' | |
import { Ayanami, ImmerReducer, useAyanami, Effect, EffectAction } from 'ayanami' | |
import type { Draft } from 'immer' | |
import React from 'react' | |
import { Observable } from 'rxjs' | |
import { map, delay } from 'rxjs/operators' | |
type ActionBuilder<State extends Record<string, any>> = Record<string, (draft: Draft<State>, arg: any) => void> | |
type EffectBuilder<State extends Record<string, any>, Actions extends Record<string, (...args: any) => void>> = Record< | |
string, | |
(this: Ayanami<State> & Actions, arg: Observable<any>) => Observable<EffectAction> | |
> | |
type ModuleFactory< | |
State extends Record<string, any> = {}, | |
Actions extends Record<string, (...args: any) => void> = {} | |
> = { | |
actions<A extends ActionBuilder<State>>(actions: A): ModuleFactory<State, A & Actions> | |
effects<E extends EffectBuilder<State, Actions>>(effects: E): ModuleFactory<State, E & Actions> | |
build(): { new (...args: any[]): Ayanami<State> & { [K in keyof Actions]: Actions[K] } } | |
} | |
function defineAyanami<State extends Record<string, any>>(state: State, name?: string): ModuleFactory<State> { | |
const module = Injectable()( | |
class extends Ayanami<State> { | |
defaultState = state | |
}, | |
) | |
name && Object.defineProperty(module, 'name', { value: name, writable: false }) | |
const factory = { | |
effects: (methods: Record<string, Function>) => { | |
Object.keys(methods).forEach((key) => { | |
module.prototype[key] = methods[key] | |
Effect()(module.prototype, key, Object.getOwnPropertyDescriptor(module, key)!) | |
}) | |
return factory | |
}, | |
actions: (actions: Record<string, Function>) => { | |
Object.keys(actions).forEach((key) => { | |
module.prototype[key] = actions[key] | |
ImmerReducer()(module.prototype, key, Object.getOwnPropertyDescriptor(module, key)!) | |
}) | |
return factory | |
}, | |
build: () => module, | |
} | |
return factory | |
} | |
// YOUR CODE STARTS HERE | |
const CounterModule = defineAyanami({ count: 0 }, 'CounterModule') | |
.actions({ | |
add: (state, amount: number) => (state.count += amount), | |
}) | |
.effects({ | |
asyncAdd(payload: Observable<number>) { | |
return payload.pipe( | |
delay(150), | |
map((count) => this.getActions().add(count)), | |
) | |
}, | |
}) | |
.build() | |
export const Apps = () => { | |
const [{ count }, { asyncAdd }] = useAyanami(CounterModule) | |
return <div onClick={() => asyncAdd(1)}>{count}</div> | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment