mobx-view-model
Version:
MobX ViewModel power for ReactJS
76 lines (75 loc) • 3.27 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
/* eslint-disable @typescript-eslint/no-use-before-define */
/* eslint-disable sonarjs/no-nested-functions */
import { observer } from 'mobx-react-lite';
import { useContext } from 'react';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import { viewModelsConfig } from '../config/global-config.js';
import { ActiveViewModelContext, ViewModelsContext, } from '../contexts/index.js';
import { useCreateViewModel, } from '../hooks/use-create-view-model.js';
/**
* Creates new instance of ViewModel
*
* [**Documentation**](https://js2me.github.io/mobx-view-model/react/api/with-view-model.html)
*/
export function withViewModel(...args) {
const VM = args[0];
let config;
let PredefinedComponent;
if (typeof args[1] === 'function') {
config = args[2] ?? {};
PredefinedComponent = args[1];
}
else {
config = args[1] ?? {};
}
const ctx = config.ctx ?? {};
ctx.VM = VM;
ctx.generateId = config?.generateId;
config.ctx = ctx;
if (PredefinedComponent) {
return withViewModelWrapper(VM, config, PredefinedComponent);
}
return (Component) => withViewModelWrapper(VM, config, Component);
}
const withViewModelWrapper = (VM, config, OriginalComponent) => {
let Component = (config.config?.processViewComponent ??
config.vmConfig?.processViewComponent ??
viewModelsConfig.processViewComponent)?.(OriginalComponent, VM, config) ?? OriginalComponent;
if (Component &&
(config.config?.wrapViewsInObserver ??
config.vmConfig?.wrapViewsInObserver ??
viewModelsConfig.wrapViewsInObserver) &&
Component.$$typeof !== Symbol.for('react.memo')) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
Component = observer(Component);
}
const ConnectedViewModel = observer((allProps) => {
const viewModels = useContext(ViewModelsContext);
config?.reactHook?.(allProps, config.ctx, viewModels);
const { payload: rawPayload, ...componentProps } = allProps;
const payload = config?.getPayload
? config.getPayload(allProps)
: rawPayload;
const instance = useCreateViewModel(VM, payload, {
...config,
component: ConnectedViewModel,
componentProps,
});
const isRenderAllowedByStore = !viewModels || viewModels.isAbleToRenderView(instance.id);
const isRenderAllowedLocally = !!instance.isMounted;
const isRenderAllowed = isRenderAllowedByStore && isRenderAllowedLocally;
if (isRenderAllowed) {
return (_jsx(ActiveViewModelContext.Provider, { value: instance, children: Component && (_jsx(Component, { ...componentProps, model: instance })) }));
}
const FallbackComponent = config?.fallback ?? viewModelsConfig.fallbackComponent;
return FallbackComponent ? (_jsx(FallbackComponent, { ...allProps, payload: payload })) : null;
});
if (process.env.NODE_ENV !== 'production') {
Object.assign(ConnectedViewModel, {
displayName: `ConnectedViewModel(${VM.name}->Component)`,
});
}
return ConnectedViewModel;
};