fix(striker-ui): avoid unneeded recreation of message setters

main
Tsu-ba-me 2 years ago
parent b99ac243ab
commit 23ea09ed35
  1. 7
      striker-ui/components/ManageManifest/AnHostInputGroup.tsx
  2. 11
      striker-ui/components/ManageManifest/AnNetworkInputGroup.tsx
  3. 4
      striker-ui/components/ManageManifest/RunManifestInputGroup.tsx
  4. 58
      striker-ui/hooks/useFormUtils.ts
  5. 41
      striker-ui/lib/buildObjectStateSetterCallback.ts
  6. 23
      striker-ui/types/BuildObjectStateSetterCallback.d.ts
  7. 2
      striker-ui/types/FormUtils.d.ts

@ -110,7 +110,6 @@ const AnHostInputGroup = <M extends MapToInputTestID>({
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
setMsgSetter,
},
hostId,
hostNumber,
@ -152,8 +151,6 @@ const AnHostInputGroup = <M extends MapToInputTestID>({
const inputId = buildInputIdAHFencePort(hostId, fenceId);
const inputLabel = `Port on ${fenceName}`;
setMsgSetter(inputId);
previous[cellId] = {
children: (
<InputWithRef
@ -196,7 +193,6 @@ const AnHostInputGroup = <M extends MapToInputTestID>({
fenceListEntries,
hostId,
msgSetters,
setMsgSetter,
],
);
@ -209,8 +205,6 @@ const AnHostInputGroup = <M extends MapToInputTestID>({
const inputId = buildInputIdAHNetworkIp(hostId, networkId);
const inputLabel = `${NETWORK_TYPES[networkType]} ${networkNumber}`;
setMsgSetter(inputId);
previous[cellId] = {
children: (
<InputWithRef
@ -251,7 +245,6 @@ const AnHostInputGroup = <M extends MapToInputTestID>({
[
networkListEntries,
hostId,
setMsgSetter,
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,

@ -1,4 +1,4 @@
import { ReactElement, ReactNode, useEffect, useMemo } from 'react';
import { ReactElement, ReactNode, useMemo } from 'react';
import NETWORK_TYPES from '../../lib/consts/NETWORK_TYPES';
@ -81,7 +81,6 @@ const AnNetworkInputGroup = <M extends MapToInputTestID>({
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
setMsgSetter,
},
inputGatewayLabel = 'Gateway',
inputMinIpLabel = 'IP address',
@ -170,8 +169,6 @@ const AnNetworkInputGroup = <M extends MapToInputTestID>({
let result: ReactNode;
if (isShowGateway && inputIdGateway) {
setMsgSetter(inputIdGateway);
result = (
<InputWithRef
input={
@ -209,7 +206,6 @@ const AnNetworkInputGroup = <M extends MapToInputTestID>({
}, [
isShowGateway,
inputIdGateway,
setMsgSetter,
networkId,
inputGatewayLabel,
previousGateway,
@ -219,11 +215,6 @@ const AnNetworkInputGroup = <M extends MapToInputTestID>({
msgSetters,
]);
useEffect(() => {
setMsgSetter(inputIdMinIp);
setMsgSetter(inputIdSubnetMask);
}, [inputIdMinIp, inputIdSubnetMask, setMsgSetter]);
return (
<InnerPanel mv={0}>
<InnerPanelHeader>

@ -36,7 +36,6 @@ const RunManifestInputGroup = <M extends MapToInputTestID>({
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
msgSetters,
setMsgSetter,
},
knownFences = {},
knownHosts = {},
@ -104,8 +103,6 @@ const RunManifestInputGroup = <M extends MapToInputTestID>({
const inputId = buildInputIdRMHost(hostId);
const inputLabel = `${prettyId} host`;
setMsgSetter(inputId);
hosts[`run-manifest-host-cell-${hostId}`] = {
children: (
<InputWithRef
@ -166,7 +163,6 @@ const RunManifestInputGroup = <M extends MapToInputTestID>({
hostListEntries,
hostOptionList,
msgSetters,
setMsgSetter,
],
);

@ -3,7 +3,9 @@ import { MutableRefObject, useCallback, useMemo, useState } from 'react';
import buildMapToMessageSetter, {
buildMessageSetter,
} from '../lib/buildMapToMessageSetter';
import buildObjectStateSetterCallback from '../lib/buildObjectStateSetterCallback';
import buildObjectStateSetterCallback, {
buildProtectedObjectStateSetterCallback,
} from '../lib/buildObjectStateSetterCallback';
import { MessageGroupForwardedRefContent } from '../components/MessageGroup';
const useFormUtils = <
@ -15,6 +17,9 @@ const useFormUtils = <
messageGroupRef: MutableRefObject<MessageGroupForwardedRefContent>,
): FormUtils<M> => {
const [formValidity, setFormValidity] = useState<FormValidity<M>>({});
const [msgSetterList, setMsgSetterList] = useState<MapToMessageSetter<M>>(
() => buildMapToMessageSetter<U, I, M>(ids, messageGroupRef),
);
const setValidity = useCallback((key: keyof M, value?: boolean) => {
setFormValidity(
@ -42,6 +47,37 @@ const useFormUtils = <
});
}, []);
const setMsgSetter = useCallback(
(
id: keyof M,
setter?: MessageSetter,
{
isOverwrite,
isUseFallback = true,
}: { isOverwrite?: boolean; isUseFallback?: boolean } = {},
) => {
const fallbackSetter: ObjectStatePropSetter<MapToMessageSetter<M>> = (
result,
key,
value = buildMessageSetter<M>(String(id), messageGroupRef),
) => {
result[key] = value;
};
setMsgSetterList(
buildProtectedObjectStateSetterCallback<MapToMessageSetter<M>>(
id,
setter,
{
isOverwrite,
set: isUseFallback ? fallbackSetter : undefined,
},
),
);
},
[messageGroupRef],
);
const buildFinishInputTestBatchFunction = useCallback(
(key: keyof M) => (result: boolean) => {
setValidity(key, result);
@ -52,9 +88,10 @@ const useFormUtils = <
const buildInputFirstRenderFunction = useCallback(
(key: keyof M) =>
({ isValid }: InputFirstRenderFunctionArgs) => {
setMsgSetter(key);
setValidity(key, isValid);
},
[setValidity],
[setMsgSetter, setValidity],
);
const isFormInvalid = useMemo(
@ -62,27 +99,12 @@ const useFormUtils = <
[formValidity],
);
const msgSetters = useMemo(
() => buildMapToMessageSetter<U, I, M>(ids, messageGroupRef),
[ids, messageGroupRef],
);
const setMsgSetter = useCallback(
(id: keyof M, setter?: MessageSetter, isOverwrite?: boolean) => {
if (!msgSetters[id] || isOverwrite) {
msgSetters[id] =
setter ?? buildMessageSetter<M>(String(id), messageGroupRef);
}
},
[messageGroupRef, msgSetters],
);
return {
buildFinishInputTestBatchFunction,
buildInputFirstRenderFunction,
formValidity,
isFormInvalid,
msgSetters,
msgSetters: msgSetterList,
setFormValidity,
setMsgSetter,
setValidity,

@ -1,13 +1,46 @@
/**
* Checks whether specified `key` is unset in given object. Always returns
* `true` when overwrite is allowed.
*/
const checkUnset = <S extends BaseObject>(
obj: S,
key: keyof S,
{ isOverwrite = false }: { isOverwrite?: boolean } = {},
): boolean => !(key in obj) || isOverwrite;
const buildObjectStateSetterCallback =
<S extends Record<string, unknown>>(key: keyof S, value?: S[keyof S]) =>
({ [key]: toReplace, ...restPrevious }: S): S => {
<S extends BaseObject>(
key: keyof S,
value?: S[keyof S],
{
guard,
set = (o, k, v) => {
if (v !== undefined) {
o[k] = v;
}
},
}: BuildObjectStateSetterCallbackOptions<S> = {},
): BuildObjectStateSetterCallbackReturnType<S> =>
(previous: S): S => {
const { [key]: toReplace, ...restPrevious } = previous;
const result = { ...restPrevious } as S;
if (value !== undefined) {
result[key] = value;
if (guard?.call(null, previous, key, value)) {
set(result, key, value);
}
return result;
};
export const buildProtectedObjectStateSetterCallback = <S extends BaseObject>(
key: keyof S,
value?: S[keyof S],
{
isOverwrite,
guard = (o, k) => checkUnset(o, k, { isOverwrite }),
set,
}: BuildObjectStateSetterCallbackOptions<S> = {},
): BuildObjectStateSetterCallbackReturnType<S> =>
buildObjectStateSetterCallback(key, value, { isOverwrite, guard, set });
export default buildObjectStateSetterCallback;

@ -0,0 +1,23 @@
type BaseObject<T = unknown> = Record<number | string | symbol, T>;
type ObjectStatePropGuard<S extends BaseObject> = (
previous: S,
key: keyof S,
value?: S[keyof S],
) => boolean;
type ObjectStatePropSetter<S extends BaseObject> = (
result: S,
key: keyof S,
value?: S[keyof S],
) => void;
type BuildObjectStateSetterCallbackOptions<S extends BaseObject> = {
guard?: ObjectStatePropGuard<S>;
isOverwrite?: boolean;
set?: ObjectStatePropSetter<S>;
};
type BuildObjectStateSetterCallbackReturnType<S extends BaseObject> = (
previous: S,
) => S;

@ -26,7 +26,7 @@ type FormUtils<M extends MapToInputTestID> = {
setMsgSetter: (
id: keyof M,
setter?: MessageSetter,
isOverwrite?: boolean,
options?: { isOverwrite?: boolean },
) => void;
setValidity: (key: keyof M, value?: boolean) => void;
setValidityRe: (re: RegExp, value?: boolean) => void;

Loading…
Cancel
Save