UNPKG

mobx-view-model

Version:
108 lines (107 loc) 3.7 kB
/* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable react-hooks/rules-of-hooks */ import { useContext, useLayoutEffect } from 'react'; import { viewModelsConfig } from '../config/global-config.js'; import { ActiveViewModelContext } from '../contexts/active-view-context.js'; import { ViewModelsContext } from '../contexts/view-models-context.js'; import { useIsomorphicLayoutEffect } from '../lib/hooks/use-isomorphic-layout-effect.js'; import { useValue } from '../lib/hooks/use-value.js'; import { generateVmId } from '../utils/generate-vm-id.js'; import { isViewModelClass } from '../utils/typeguards.js'; /** * Creates new instance of ViewModel * * [**Documentation**](https://js2me.github.io/mobx-view-model/react/api/use-create-view-model.html) */ export function useCreateViewModel(VM, payload, config) { if (isViewModelClass(VM)) { // scenario for ViewModelBase return useCreateViewModelBase(VM, payload, config); } // scenario for ViewModelSimple return useCreateViewModelSimple(VM, payload); } const useCreateViewModelBase = (VM, payload, config) => { const viewModels = useContext(ViewModelsContext); const parentViewModel = useContext(ActiveViewModelContext) || null; const ctx = config?.ctx ?? {}; const instance = useValue(() => { const id = viewModels?.generateViewModelId({ ...config, ctx, VM, parentViewModelId: parentViewModel?.id, }) ?? config?.id ?? generateVmId(ctx); const instanceFromStore = viewModels ? viewModels.get(id) : null; if (instanceFromStore) { return instanceFromStore; } else { const configCreate = { ...config, vmConfig: config?.config ?? config?.vmConfig, id, parentViewModelId: parentViewModel?.id, payload: payload ?? {}, VM, viewModels, parentViewModel, ctx, }; viewModels?.processCreateConfig(configCreate); const instance = config?.factory?.(configCreate) ?? viewModels?.createViewModel(configCreate) ?? viewModelsConfig.factory(configCreate); instance.willMount(); viewModels?.markToBeAttached(instance); return instance; } }); useIsomorphicLayoutEffect(() => { if (viewModels) { viewModels.attach(instance); return () => { viewModels.detach(instance.id); }; } else { instance.mount(); return () => { instance.willUnmount(); instance.unmount(); }; } }, [instance]); instance.setPayload(payload ?? {}); return instance; }; const useCreateViewModelSimple = (VM, payload) => { const viewModels = useContext(ViewModelsContext); const instance = useValue(() => { const instance = new VM(); viewModels?.markToBeAttached(instance); return instance; }); if ('setPayload' in instance) { useLayoutEffect(() => { instance.setPayload(payload); }, [payload]); } useIsomorphicLayoutEffect(() => { if (viewModels) { viewModels.attach(instance); return () => { viewModels.detach(instance.id); }; } else { instance.mount?.(); return () => { instance.unmount?.(); }; } }, [instance]); return instance; };