@mic-rexjs/usecases-react
Version:
React-based solution for use usecases of Clean Architecture
101 lines • 3.38 kB
JavaScript
import { useConstantEntityReducers } from '../useConstantEntityReducers';
import { useExec } from '../useExec';
import { useLatest, useMemoizedFn, useUnmount, useUpdate, useUpdateEffect } from 'ahooks';
import { useEffect, useRef } from 'react';
import { Statuses } from '../../enums/Statuses';
import { triggerWatchers } from '../../methods/triggerWatchers';
import { valueUseCase } from '../../usecases/valueUseCase';
export const useEntity = (entityArg, store, reducers, statuses, options) => {
const update = useUpdate();
const isFunction = typeof entityArg === 'function';
const entity = store.value;
const isFirstRef = useRef(true);
const optionsRef = useLatest(options);
const prevEntityRef = useRef(entity);
const entityEnabled = (statuses & Statuses.EntityEnabled) === Statuses.EntityEnabled;
const entityRootEnabled = (statuses & Statuses.EntityRootEnabled) === Statuses.EntityRootEnabled;
const bindEntity = reducers.bindEntity,
unbindEntity = reducers.unbindEntity;
const _useConstantEntityRed = useConstantEntityReducers(entityArg, valueUseCase),
isValueChanged = _useConstantEntityRed.isValueChanged,
recordValue = _useConstantEntityRed.recordValue;
const onTriggerWatchers = useMemoizedFn((newEntity, oldEntity) => {
const watch = optionsRef.current.watch;
if (!watch) {
return;
}
triggerWatchers(watch, newEntity, oldEntity);
});
const onEntityChange = useMemoizedFn((newEntity, oldEntity) => {
const onChange = optionsRef.current.onChange;
prevEntityRef.current = newEntity;
onTriggerWatchers(newEntity, oldEntity);
onChange === null || onChange === void 0 || onChange(newEntity, oldEntity);
if (!entityRootEnabled) {
return;
}
update();
});
const onValueChange = useMemoizedFn(() => {
if (!entityEnabled) {
return;
}
const prevEntity = prevEntityRef.current;
if (entity === prevEntity) {
return;
}
prevEntityRef.current = entity;
onTriggerWatchers(entity, prevEntity);
});
useExec(() => {
const isFirst = isFirstRef.current;
isFirstRef.current = false;
if (!entityRootEnabled) {
return;
}
if (isFirst) {
// 这里不要修改 `entity`,因为 `useUseCase` 有初始化 `entity` 的逻辑
bindEntity === null || bindEntity === void 0 || bindEntity();
}
if (isFunction) {
return;
}
const isChanged = isValueChanged(entityArg);
if (!isChanged) {
return;
}
recordValue(entityArg);
store.disableWatchers();
// 执行同步操作
store.setValue(entityArg);
store.enableWatchers();
});
/**
* 需要马上 `watch`,因为 `useEffect` 在子组件内优先执行,
* 如果使用了 `setEntity` 则无法监控到变化
*/
useExec(() => {
if (!entityEnabled) {
return;
}
store.watch(onEntityChange);
}, [entityEnabled, store, onEntityChange]);
/**
* 在变化时候,组件更新前,使用 `unwatch`
*/
useEffect(() => {
return () => {
store.unwatch(onEntityChange);
};
}, [entityEnabled, store, onEntityChange]);
useUnmount(() => {
if (!entityRootEnabled) {
return;
}
unbindEntity === null || unbindEntity === void 0 || unbindEntity();
});
useUpdateEffect(() => {
onValueChange();
}, [entity, onValueChange]);
return store.value;
};