Skip to content

Commit a038ba3

Browse files
authored
Release/0.9.0 (#154)
* fix: 🐛 update props field when change * feat: 🎸 useObserveEffect support function
1 parent cf4045d commit a038ba3

File tree

10 files changed

+53
-12
lines changed

10 files changed

+53
-12
lines changed

example/src/Dev.tsx

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,46 @@
1+
import { ReflectiveInjector } from 'injection-js';
12
import React from 'react';
23

34
import { CounterSpeed } from './components/Counter';
5+
import { TodoApp } from './components/Todo';
6+
import { TodoService } from './services/TodoService';
47

5-
import { StatedBeanApplication, StatedBeanProvider } from 'stated-bean';
8+
import { StatedBeanApplication, StatedBeanProvider, IBeanFactory, BeanDefinition } from 'stated-bean';
69

710
const app = new StatedBeanApplication();
811

12+
class InjectionFactory implements IBeanFactory {
13+
rootInjector = ReflectiveInjector.resolveAndCreate([TodoService]);
14+
15+
createBean<T>(beanDefinition: BeanDefinition<T>) {
16+
let provide;
17+
let provider;
18+
19+
if (beanDefinition.isFactoryBean) {
20+
provide = beanDefinition.factoryBeanType;
21+
provider = { provide: provide, useFactory: beanDefinition.getFactory()! };
22+
} else {
23+
provide = beanDefinition.beanType;
24+
provider = { provide: provide, useClass: beanDefinition.beanType };
25+
}
26+
const injector = ReflectiveInjector.resolveAndCreate([provider], this.rootInjector);
27+
28+
return injector.get(provide);
29+
}
30+
31+
destroyBean<T>(beanDefinition: BeanDefinition<T>) {
32+
console.info('destroyed', beanDefinition);
33+
}
34+
}
35+
36+
app.setBeanFactory(new InjectionFactory());
37+
938
export const DevApp = () => {
1039
return (
1140
<StatedBeanProvider application={app}>
1241
<CounterSpeed />
42+
43+
<TodoApp />
1344
</StatedBeanProvider>
1445
);
1546
};

example/src/components/Todo/index.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Todo } from '../../services/TodoService';
44

55
import { TodoModel } from './model';
66

7-
import { useInject, useObserveEffect } from 'stated-bean';
7+
import { useBean, useObserveEffect } from 'stated-bean';
88

99
function TodoList(props: { items: Todo[] }) {
1010
return (
@@ -17,8 +17,9 @@ function TodoList(props: { items: Todo[] }) {
1717
}
1818

1919
export const TodoApp = () => {
20-
const todo = useInject(TodoModel);
21-
const { loading, error } = useObserveEffect(todo, 'fetchTodo');
20+
const todo = useBean(TodoModel);
21+
// eslint-disable-next-line @typescript-eslint/unbound-method
22+
const { loading, error } = useObserveEffect(todo, todo.fetchTodo);
2223

2324
console.log(loading, error, todo.todoList);
2425
return (

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "stated-bean",
3-
"version": "0.8.6",
3+
"version": "0.9.0",
44
"description": "A light but scalable state management library with react hooks",
55
"repository": "[email protected]:mjolnirjs/stated-bean.git",
66
"license": "MIT",

src/core/BeanObserver.ts

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export class BeanObserver<T = unknown> {
178178
} else {
179179
Reflect.set((bean as unknown) as object, field.name, newValue);
180180
}
181+
Reflect.set((bean as unknown) as object, field.name, newValue);
181182
}
182183
}
183184
}

src/decorator/Effect.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { getBeanWrapper, isPromise } from '../utils';
66
* @export
77
* @returns {MethodDecorator}
88
*/
9-
export function Effect(name?: string | symbol): MethodDecorator {
9+
export function Effect(): MethodDecorator {
1010
return (
1111
prototype,
1212
propertyKey,
@@ -16,7 +16,7 @@ export function Effect(name?: string | symbol): MethodDecorator {
1616
if (descriptor === undefined) {
1717
descriptor = Object.getOwnPropertyDescriptor(prototype, propertyKey)!;
1818
}
19-
const effectName = name || propertyKey;
19+
const effectName = propertyKey;
2020
const originalMethod: Function = descriptor.value;
2121

2222
descriptor.value = function<T>(this: T, ...args: unknown[]) {
@@ -29,6 +29,7 @@ export function Effect(name?: string | symbol): MethodDecorator {
2929
if (observer !== undefined) {
3030
observer.effect$.next({
3131
effect: effectName,
32+
effectTarget: Reflect.get((this as unknown) as object, effectName),
3233
...action,
3334
} as EffectAction<T>);
3435
}

src/hooks/useObserveEffect.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useCallback, useContext, useEffect, useState } from 'react';
22

33
import { getStatedBeanContext } from '../context';
4-
import { EffectAction, FunctionPropertyNames } from '../types';
4+
import { EffectAction, FunctionPropertyNames, FunctionProperty } from '../types';
55
import { getBeanWrapper } from '../utils';
66

77
/**
@@ -13,7 +13,7 @@ import { getBeanWrapper } from '../utils';
1313
* @param {FunctionPropertyNames<T>} effect
1414
* @returns {EffectAction}
1515
*/
16-
export function useObserveEffect<T>(bean: T, effect: FunctionPropertyNames<T> | string | symbol): EffectAction {
16+
export function useObserveEffect<T>(bean: T, effect: FunctionPropertyNames<T> | FunctionProperty<T>): EffectAction {
1717
const StateBeanContext = getStatedBeanContext();
1818
const context = useContext(StateBeanContext);
1919
const container = context.container;
@@ -32,7 +32,8 @@ export function useObserveEffect<T>(bean: T, effect: FunctionPropertyNames<T> |
3232

3333
const listener = useCallback(
3434
(action: EffectAction) => {
35-
if (action.effect === effect) {
35+
console.log(action.effectTarget === effect);
36+
if (action.effect === effect || action.effectTarget === effect) {
3637
setEffectState(action);
3738
}
3839
},

src/types/Actions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export interface EffectAction<T = unknown> {
1212
data: T;
1313
error: unknown;
1414
effect: string | symbol;
15+
effectTarget?: Function;
1516
}
1617

1718
export interface LifeCycleAction<T = unknown> {

src/types/ClassType.ts

+5
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ export type InstanceType<T extends ClassType<T>> = T extends ClassType<infer R>
88
export type FunctionPropertyNames<T> = {
99
[K in keyof T]: T[K] extends Function ? K : never;
1010
}[keyof T];
11+
12+
// eslint-disable-next-line @typescript-eslint/no-type-alias
13+
export type FunctionProperty<T> = {
14+
[K in keyof T]: T[K] extends Function ? T[K] : never;
15+
}[keyof T];

test/effect-action.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class PostProvidedSample {
1111
@Stated()
1212
test = 0;
1313

14-
@Effect('add')
14+
@Effect()
1515
async add() {
1616
await delay(100);
1717
this.test += 1;

test/props.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ describe('props observer test', () => {
4545

4646
rerender({ value: 20 });
4747

48-
expect(result.current.value3).toBe(10);
48+
expect(result.current.value3).toBe(20);
4949
expect(result.current.value4).toBe(20);
5050
expect(result.current.value.getValue()).toBe(20);
5151
expect(result.current.value$.getValue()).toBe(20);

0 commit comments

Comments
 (0)