TeactN: Introduce stickToFirst

This commit is contained in:
Alexander Zinchuk 2023-11-06 01:43:17 +04:00
parent 3d12a47866
commit f894010a70

View File

@ -14,6 +14,17 @@ import useUniqueId from '../../hooks/useUniqueId';
export default React; export default React;
interface Container {
mapStateToProps: MapStateToProps<any>;
activationFn?: ActivationFn<any>;
stuckTo?: any;
ownProps: Props;
mappedProps?: Props;
forceUpdate: Function;
DEBUG_updates: number;
DEBUG_componentName: string;
}
type GlobalState = type GlobalState =
AnyLiteral AnyLiteral
& { DEBUG_capturedId?: number }; & { DEBUG_capturedId?: number };
@ -36,7 +47,10 @@ type ActionHandler = (
) => GlobalState | void | Promise<void>; ) => GlobalState | void | Promise<void>;
type MapStateToProps<OwnProps = undefined> = (global: GlobalState, ownProps: OwnProps) => AnyLiteral; type MapStateToProps<OwnProps = undefined> = (global: GlobalState, ownProps: OwnProps) => AnyLiteral;
type ActivationFn<OwnProps = undefined> = (global: GlobalState, ownProps: OwnProps) => boolean; type StickToFirstFn = (value: any) => boolean;
type ActivationFn<OwnProps = undefined> = (
global: GlobalState, ownProps: OwnProps, stickToFirst: StickToFirstFn,
) => boolean;
let currentGlobal = {} as GlobalState; let currentGlobal = {} as GlobalState;
@ -50,15 +64,7 @@ const DEBUG_releaseCapturedIdThrottled = throttleWithTickEnd(() => {
const actionHandlers: Record<string, ActionHandler[]> = {}; const actionHandlers: Record<string, ActionHandler[]> = {};
const callbacks: Function[] = [updateContainers]; const callbacks: Function[] = [updateContainers];
const actions = {} as Actions; const actions = {} as Actions;
const containers = new Map<string, { const containers = new Map<string, Container>();
mapStateToProps: MapStateToProps<any>;
activationFn?: ActivationFn<any>;
ownProps: Props;
mappedProps?: Props;
forceUpdate: Function;
DEBUG_updates: number;
DEBUG_componentName: string;
}>();
const runCallbacksThrottled = throttleWithTickEnd(runCallbacks); const runCallbacksThrottled = throttleWithTickEnd(runCallbacks);
@ -161,10 +167,10 @@ function updateContainers() {
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const container of containers.values()) { for (const container of containers.values()) {
const { const {
mapStateToProps, activationFn, ownProps, mappedProps, forceUpdate, mapStateToProps, ownProps, mappedProps, forceUpdate,
} = container; } = container;
if (activationFn && !activationFn(currentGlobal, ownProps)) { if (!activateContainer(container, currentGlobal, ownProps)) {
continue; continue;
} }
@ -266,8 +272,7 @@ export function withGlobal<OwnProps extends AnyLiteral>(
} }
if (!container.mappedProps || ( if (!container.mappedProps || (
!arePropsShallowEqual(container.ownProps, props) !arePropsShallowEqual(container.ownProps, props) && activateContainer(container, currentGlobal, props)
&& (!activationFn || activationFn(currentGlobal, props))
)) { )) {
try { try {
container.mappedProps = mapStateToProps(currentGlobal, props); container.mappedProps = mapStateToProps(currentGlobal, props);
@ -288,6 +293,21 @@ export function withGlobal<OwnProps extends AnyLiteral>(
}; };
} }
function activateContainer(container: Container, global: GlobalState, props: Props) {
const { activationFn, stuckTo } = container;
if (!activationFn) {
return true;
}
return activationFn(global, props, (stickTo: any) => {
if (stickTo && !stuckTo) {
container.stuckTo = stickTo;
}
return stickTo && (!stuckTo || stuckTo === stickTo);
});
}
export function typify< export function typify<
ProjectGlobalState, ProjectGlobalState,
ActionPayloads, ActionPayloads,
@ -322,7 +342,7 @@ export function typify<
) => void, ) => void,
withGlobal: withGlobal as <OwnProps extends AnyLiteral>( withGlobal: withGlobal as <OwnProps extends AnyLiteral>(
mapStateToProps: (global: ProjectGlobalState, ownProps: OwnProps) => AnyLiteral, mapStateToProps: (global: ProjectGlobalState, ownProps: OwnProps) => AnyLiteral,
activationFn?: (global: ProjectGlobalState, ownProps: OwnProps) => boolean, activationFn?: (global: ProjectGlobalState, ownProps: OwnProps, stickToFirst: StickToFirstFn) => boolean,
) => (Component: FC) => FC<OwnProps>, ) => (Component: FC) => FC<OwnProps>,
}; };
} }