Skip to content

Commit

Permalink
Release/0.9.0 (#154)
Browse files Browse the repository at this point in the history
* fix: 🐛 update props field when change

* feat: 🎸 useObserveEffect support function
  • Loading branch information
foreleven authored Mar 7, 2020
1 parent cf4045d commit a038ba3
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 12 deletions.
33 changes: 32 additions & 1 deletion example/src/Dev.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,46 @@
import { ReflectiveInjector } from 'injection-js';
import React from 'react';

import { CounterSpeed } from './components/Counter';
import { TodoApp } from './components/Todo';
import { TodoService } from './services/TodoService';

import { StatedBeanApplication, StatedBeanProvider } from 'stated-bean';
import { StatedBeanApplication, StatedBeanProvider, IBeanFactory, BeanDefinition } from 'stated-bean';

const app = new StatedBeanApplication();

class InjectionFactory implements IBeanFactory {
rootInjector = ReflectiveInjector.resolveAndCreate([TodoService]);

createBean<T>(beanDefinition: BeanDefinition<T>) {
let provide;
let provider;

if (beanDefinition.isFactoryBean) {
provide = beanDefinition.factoryBeanType;
provider = { provide: provide, useFactory: beanDefinition.getFactory()! };
} else {
provide = beanDefinition.beanType;
provider = { provide: provide, useClass: beanDefinition.beanType };
}
const injector = ReflectiveInjector.resolveAndCreate([provider], this.rootInjector);

return injector.get(provide);
}

destroyBean<T>(beanDefinition: BeanDefinition<T>) {
console.info('destroyed', beanDefinition);
}
}

app.setBeanFactory(new InjectionFactory());

export const DevApp = () => {
return (
<StatedBeanProvider application={app}>
<CounterSpeed />

<TodoApp />
</StatedBeanProvider>
);
};
7 changes: 4 additions & 3 deletions example/src/components/Todo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Todo } from '../../services/TodoService';

import { TodoModel } from './model';

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

function TodoList(props: { items: Todo[] }) {
return (
Expand All @@ -17,8 +17,9 @@ function TodoList(props: { items: Todo[] }) {
}

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

console.log(loading, error, todo.todoList);
return (
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stated-bean",
"version": "0.8.6",
"version": "0.9.0",
"description": "A light but scalable state management library with react hooks",
"repository": "git@github.com:mjolnirjs/stated-bean.git",
"license": "MIT",
Expand Down
1 change: 1 addition & 0 deletions src/core/BeanObserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export class BeanObserver<T = unknown> {
} else {
Reflect.set((bean as unknown) as object, field.name, newValue);
}
Reflect.set((bean as unknown) as object, field.name, newValue);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/decorator/Effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getBeanWrapper, isPromise } from '../utils';
* @export
* @returns {MethodDecorator}
*/
export function Effect(name?: string | symbol): MethodDecorator {
export function Effect(): MethodDecorator {
return (
prototype,
propertyKey,
Expand All @@ -16,7 +16,7 @@ export function Effect(name?: string | symbol): MethodDecorator {
if (descriptor === undefined) {
descriptor = Object.getOwnPropertyDescriptor(prototype, propertyKey)!;
}
const effectName = name || propertyKey;
const effectName = propertyKey;
const originalMethod: Function = descriptor.value;

descriptor.value = function<T>(this: T, ...args: unknown[]) {
Expand All @@ -29,6 +29,7 @@ export function Effect(name?: string | symbol): MethodDecorator {
if (observer !== undefined) {
observer.effect$.next({
effect: effectName,
effectTarget: Reflect.get((this as unknown) as object, effectName),
...action,
} as EffectAction<T>);
}
Expand Down
7 changes: 4 additions & 3 deletions src/hooks/useObserveEffect.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useCallback, useContext, useEffect, useState } from 'react';

import { getStatedBeanContext } from '../context';
import { EffectAction, FunctionPropertyNames } from '../types';
import { EffectAction, FunctionPropertyNames, FunctionProperty } from '../types';
import { getBeanWrapper } from '../utils';

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

const listener = useCallback(
(action: EffectAction) => {
if (action.effect === effect) {
console.log(action.effectTarget === effect);
if (action.effect === effect || action.effectTarget === effect) {
setEffectState(action);
}
},
Expand Down
1 change: 1 addition & 0 deletions src/types/Actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface EffectAction<T = unknown> {
data: T;
error: unknown;
effect: string | symbol;
effectTarget?: Function;
}

export interface LifeCycleAction<T = unknown> {
Expand Down
5 changes: 5 additions & 0 deletions src/types/ClassType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,8 @@ export type InstanceType<T extends ClassType<T>> = T extends ClassType<infer R>
export type FunctionPropertyNames<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];

// eslint-disable-next-line @typescript-eslint/no-type-alias
export type FunctionProperty<T> = {
[K in keyof T]: T[K] extends Function ? T[K] : never;
}[keyof T];
2 changes: 1 addition & 1 deletion test/effect-action.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class PostProvidedSample {
@Stated()
test = 0;

@Effect('add')
@Effect()
async add() {
await delay(100);
this.test += 1;
Expand Down
2 changes: 1 addition & 1 deletion test/props.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('props observer test', () => {

rerender({ value: 20 });

expect(result.current.value3).toBe(10);
expect(result.current.value3).toBe(20);
expect(result.current.value4).toBe(20);
expect(result.current.value.getValue()).toBe(20);
expect(result.current.value$.getValue()).toBe(20);
Expand Down

0 comments on commit a038ba3

Please sign in to comment.