UNPKG

mobx-keystone-mindreframer

Version:

A MobX powered state management solution based on data trees with first class support for Typescript, snapshots, patches and much more

80 lines (70 loc) 2.3 kB
import { action } from "mobx" import { ActionContextActionType } from "../action/context" import { HookAction } from "../action/hookActions" import { wrapInAction, wrapModelMethodInActionIfNeeded } from "../action/wrapInAction" import type { AnyModel } from "../model/BaseModel" import { _BaseModel } from "../model/_BaseModel" import { walkTree, WalkTreeMode } from "../parent/walkTree" const onAttachedDisposers = new WeakMap<object, () => void>() /** * @ignore * @internal */ export const attachToRootStore = action( "attachToRootStore", (rootStore: object, child: object): void => { // we use an array to ensure they will get called even if the actual hook modifies the tree const childrenToCall: AnyModel[] = [] walkTree( child, (ch) => { if (ch instanceof _BaseModel && (ch as any).onAttachedToRootStore) { wrapModelMethodInActionIfNeeded( ch as any, "onAttachedToRootStore", HookAction.OnAttachedToRootStore ) childrenToCall.push(ch as AnyModel) } }, WalkTreeMode.ParentFirst ) const childrenToCallLen = childrenToCall.length for (let i = 0; i < childrenToCallLen; i++) { const ch = childrenToCall[i] const disposer = (ch as any).onAttachedToRootStore!(rootStore) if (disposer) { onAttachedDisposers.set(ch, disposer) } } } ) /** * @ignore * @internal */ export const detachFromRootStore = action("detachFromRootStore", (child: object): void => { // we use an array to ensure they will get called even if the actual hook modifies the tree const disposersToCall: (() => void)[] = [] walkTree( child, (ch) => { const disposer = onAttachedDisposers.get(ch) if (disposer) { // wrap disposer in action const disposerAction = wrapInAction({ nameOrNameFn: HookAction.OnAttachedToRootStoreDisposer, fn: disposer, actionType: ActionContextActionType.Sync, }).bind(ch) onAttachedDisposers.delete(ch) disposersToCall.push(disposerAction) } }, WalkTreeMode.ChildrenFirst ) const disposersToCallLen = disposersToCall.length for (let i = 0; i < disposersToCallLen; i++) { disposersToCall[i]() } })