diff --git a/lib/js/useMobxEffect.tsx b/lib/js/useMobxEffect.tsx index 78e5742..a7ac8e9 100644 --- a/lib/js/useMobxEffect.tsx +++ b/lib/js/useMobxEffect.tsx @@ -1,30 +1,64 @@ import { useMount } from './useMount'; -import { Subscription } from 'rxjs'; -import { reaction, toJS } from 'mobx' -import { useMobxState } from './useMobxState'; -import { useEffect } from 'react'; +import { ReplaySubject, Subscription, tap } from 'rxjs'; +import { observable, reaction, toJS } from 'mobx' +import { useEffect, useRef } from 'react'; +import { extendObservable, remove, isObservable, runInAction } from 'mobx'; export const useMobxEffect = (callback: () => void, dependencyList?: any[]): void => { - const state = useMobxState({ - }, { callback }) + const callbackRef = useRef<{ callback: () => void }>({ callback: callback }); - const source = useMobxState({}, Object.assign({}, dependencyList)); + const subjectRef = useRef(new ReplaySubject(1)); + + const dependencyListRef = useRef(dependencyList); + + callbackRef.current!.callback = callback; + + dependencyListRef.current = dependencyList; useEffect(() => { - if (!dependencyList) { - callback() + if (dependencyList) { + return; } + callback(); }) - useMount((subscription) => { - if (dependencyList) { - const disposer = reaction(() => [toJS(source)], () => state.callback(), { fireImmediately: true, delay: 1 }); + useEffect(() => { + if (!dependencyList) { + return; + } + subjectRef.current.next(); + }, dependencyList) - subscription.add(new Subscription(() => { - disposer(); - })); + useMount((subscription) => { + if (!dependencyList) { + return; } + const mobxData = observable(Object.assign({}, dependencyListRef.current)); + subscription.add(subjectRef.current.pipe( + tap(() => { + runInAction(() => { + const props = Object.assign({}, dependencyListRef.current); + for (const key in props) { + if (isObservable(props[key]) || Object.getOwnPropertyDescriptor(props, key)?.get) { + Object.defineProperty(mobxData, key, Object.getOwnPropertyDescriptor(props, key) as any) + } else { + if (props[key] !== mobxData[key]) { + remove(mobxData, key); + extendObservable(mobxData, { [key]: props[key] }, { [key]: false }) + } + } + } + }) + }) + ).subscribe()); + + const disposer = reaction(() => [toJS(mobxData)], () => callbackRef.current!.callback(), { fireImmediately: true, delay: 1 }); + + subscription.add(new Subscription(() => { + disposer(); + })); + }) } \ No newline at end of file diff --git a/package.json b/package.json index c2a56e1..3ffcbd4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mobx-react-use-autorun", - "version": "4.0.30", + "version": "4.0.31-beta", "description": "Provide concise usage for mobx in react", "scripts": { "test": "npx -y -p typescript -p ts-node ts-node --skipProject bin/mobx_react_test.ts",