fix(striker-ui): don't create functions on re-render

main
Tsu-ba-me 2 years ago
parent 17ca3a0f32
commit 5ce3277a6e
  1. 214
      striker-ui/components/GeneralInitForm.tsx
  2. 1
      striker-ui/components/InputWithRef.tsx
  3. 20
      striker-ui/components/SuggestButton.tsx

@ -1,11 +1,12 @@
import { Box as MUIBox } from '@mui/material'; import { Box as MUIBox } from '@mui/material';
import { forwardRef, useImperativeHandle, useRef } from 'react'; import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import createFunction from '../lib/createFunction';
import FlexBox from './FlexBox'; import FlexBox from './FlexBox';
import InputWithRef, { InputForwardedRefContent } from './InputWithRef'; import InputWithRef, { InputForwardedRefContent } from './InputWithRef';
import isEmpty from '../lib/isEmpty'; import isEmpty from '../lib/isEmpty';
import OutlinedInputWithLabel from './OutlinedInputWithLabel'; import OutlinedInputWithLabel, {
OutlinedInputWithLabelProps,
} from './OutlinedInputWithLabel';
import pad from '../lib/pad'; import pad from '../lib/pad';
import SuggestButton from './SuggestButton'; import SuggestButton from './SuggestButton';
@ -19,6 +20,11 @@ type GeneralInitFormForwardRefContent = {
}; };
}; };
type OutlinedInputWithLabelOnBlur = Exclude<
OutlinedInputWithLabelProps['inputProps'],
undefined
>['onBlur'];
const MAX_ORGANIZATION_PREFIX_LENGTH = 5; const MAX_ORGANIZATION_PREFIX_LENGTH = 5;
const MIN_ORGANIZATION_PREFIX_LENGTH = 2; const MIN_ORGANIZATION_PREFIX_LENGTH = 2;
const MAX_HOST_NUMBER_LENGTH = 2; const MAX_HOST_NUMBER_LENGTH = 2;
@ -60,6 +66,13 @@ const buildHostName = ({
const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>( const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
(generalInitFormProps, ref) => { (generalInitFormProps, ref) => {
const [
isShowOrganizationPrefixSuggest,
setIsShowOrganizationPrefixSuggest,
] = useState<boolean>(false);
const [isShowHostNameSuggest, setIsShowHostNameSuggest] =
useState<boolean>(false);
const organizationNameInputRef = useRef<InputForwardedRefContent<'string'>>( const organizationNameInputRef = useRef<InputForwardedRefContent<'string'>>(
{}, {},
); );
@ -99,51 +112,48 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
return hostName; return hostName;
}; };
const populateOrganizationPrefixInputOnBlur = createFunction( const isOrganizationPrefixPrereqFilled = () =>
{ isEmpty([organizationNameInputRef.current.getValue?.call(null)], {
condition: not: true,
!organizationPrefixInputRef.current.getIsChangedByUser?.call(null), });
}, const isHostNamePrereqFilled = () =>
populateOrganizationPrefixInput, isEmpty(
); [
const populateHostNameInputOnBlur = createFunction( organizationPrefixInputRef.current.getValue?.call(null),
{ condition: !hostNameInputRef.current.getIsChangedByUser?.call(null) }, hostNumberInputRef.current.getValue?.call(null),
populateHostNameInput, domainNameInputRef.current.getValue?.call(null),
); ],
const handleOrganizationPrefixSuggest = createFunction( {
{ not: true,
conditionFn: () => },
organizationPrefixInputRef.current.getIsChangedByUser?.call(null) === );
true && const populateOrganizationPrefixInputOnBlur: OutlinedInputWithLabelOnBlur =
isEmpty([organizationNameInputRef.current.getValue?.call(null)], {
not: true,
}),
},
() => { () => {
const organizationPrefix = populateOrganizationPrefixInput(); if (organizationPrefixInputRef.current.getIsChangedByUser?.call(null)) {
setIsShowOrganizationPrefixSuggest(
if (!hostNameInputRef.current.getIsChangedByUser?.call(null)) { isOrganizationPrefixPrereqFilled(),
populateHostNameInput({ organizationPrefix }); );
} else {
populateOrganizationPrefixInput();
} }
}, };
); const populateHostNameInputOnBlur: OutlinedInputWithLabelOnBlur = () => {
const handlerHostNameSuggest = createFunction( if (hostNameInputRef.current.getIsChangedByUser?.call(null)) {
{ setIsShowHostNameSuggest(isHostNamePrereqFilled());
conditionFn: () => } else {
hostNameInputRef.current.getIsChangedByUser?.call(null) === true && populateHostNameInput();
isEmpty( }
[ };
organizationPrefixInputRef.current.getValue?.call(null), const handleOrganizationPrefixSuggest = () => {
hostNumberInputRef.current.getValue?.call(null), const organizationPrefix = populateOrganizationPrefixInput();
domainNameInputRef.current.getValue?.call(null),
], if (!hostNameInputRef.current.getIsChangedByUser?.call(null)) {
{ populateHostNameInput({ organizationPrefix });
not: true, }
}, };
), const handlerHostNameSuggest = () => {
}, populateHostNameInput();
populateHostNameInput, };
);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
get: () => ({ get: () => ({
@ -188,32 +198,62 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
} }
ref={organizationNameInputRef} ref={organizationNameInputRef}
/> />
<InputWithRef <FlexBox row>
input={ <InputWithRef
<OutlinedInputWithLabel input={
helpMessageBoxProps={{ <OutlinedInputWithLabel
text: "Alphanumberic short-form of the organization name. It's used as the prefix for host names.", helpMessageBoxProps={{
}} text: "Alphanumberic short-form of the organization name. It's used as the prefix for host names.",
id="striker-init-general-organization-prefix" }}
inputProps={{ id="striker-init-general-organization-prefix"
endAdornment: ( inputProps={{
<SuggestButton onClick={handleOrganizationPrefixSuggest} /> endAdornment: (
), <SuggestButton
inputProps: { show={isShowOrganizationPrefixSuggest}
maxLength: MAX_ORGANIZATION_PREFIX_LENGTH, onClick={handleOrganizationPrefixSuggest}
style: { width: '2.5em' }, />
}, ),
onBlur: populateHostNameInputOnBlur, inputProps: {
sx: { maxLength: MAX_ORGANIZATION_PREFIX_LENGTH,
minWidth: 'min-content', style: { width: '2.5em' },
width: 'fit-content', },
}, onBlur: populateHostNameInputOnBlur,
}} sx: {
label="Prefix" minWidth: 'min-content',
/> width: 'fit-content',
} },
ref={organizationPrefixInputRef} }}
/> label="Prefix"
onChange={() => {
setIsShowOrganizationPrefixSuggest(
isOrganizationPrefixPrereqFilled(),
);
}}
/>
}
ref={organizationPrefixInputRef}
/>
<InputWithRef
input={
<OutlinedInputWithLabel
helpMessageBoxProps={{
text: "Number or count of this striker; this should be '1' for the first striker, '2' for the second striker, and such.",
}}
id="striker-init-general-host-number"
inputProps={{
inputProps: { maxLength: MAX_HOST_NUMBER_LENGTH },
onBlur: populateHostNameInputOnBlur,
sx: {
width: '5em',
},
}}
label="Host #"
/>
}
ref={hostNumberInputRef}
valueType="number"
/>
</FlexBox>
</FlexBox> </FlexBox>
<FlexBox> <FlexBox>
<InputWithRef <InputWithRef
@ -227,7 +267,6 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
onBlur: populateHostNameInputOnBlur, onBlur: populateHostNameInputOnBlur,
sx: { sx: {
minWidth: { sm: '16em' }, minWidth: { sm: '16em' },
width: { xs: '100%', sm: '50%' },
}, },
}} }}
label="Domain name" label="Domain name"
@ -235,26 +274,7 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
} }
ref={domainNameInputRef} ref={domainNameInputRef}
/> />
<InputWithRef
input={
<OutlinedInputWithLabel
helpMessageBoxProps={{
text: "Number or count of this striker; this should be '1' for the first striker, '2' for the second striker, and such.",
}}
id="striker-init-general-host-number"
inputProps={{
inputProps: { maxLength: MAX_HOST_NUMBER_LENGTH },
onBlur: populateHostNameInputOnBlur,
sx: {
width: '5em',
},
}}
label="Host #"
/>
}
ref={hostNumberInputRef}
valueType="number"
/>
<InputWithRef <InputWithRef
input={ input={
<OutlinedInputWithLabel <OutlinedInputWithLabel
@ -264,7 +284,10 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
id="striker-init-general-host-name" id="striker-init-general-host-name"
inputProps={{ inputProps={{
endAdornment: ( endAdornment: (
<SuggestButton onClick={handlerHostNameSuggest} /> <SuggestButton
show={isShowHostNameSuggest}
onClick={handlerHostNameSuggest}
/>
), ),
inputProps: { inputProps: {
style: { style: {
@ -276,6 +299,9 @@ const GeneralInitForm = forwardRef<GeneralInitFormForwardRefContent>(
}, },
}} }}
label="Host name" label="Host name"
onChange={() => {
setIsShowHostNameSuggest(isHostNamePrereqFilled());
}}
/> />
} }
ref={hostNameInputRef} ref={hostNameInputRef}

@ -66,6 +66,7 @@ const InputWithRef = forwardRef(
const onChange = createInputOnChangeHandler<TypeName>({ const onChange = createInputOnChangeHandler<TypeName>({
postSet: (...args) => { postSet: (...args) => {
setIsChangedByUser(true); setIsChangedByUser(true);
input.props.onChange?.call(null, ...args);
postSetAppend?.call(null, ...args); postSetAppend?.call(null, ...args);
}, },
set: setValue, set: setValue,

@ -2,8 +2,22 @@ import { FC } from 'react';
import ContainedButton, { ContainedButtonProps } from './ContainedButton'; import ContainedButton, { ContainedButtonProps } from './ContainedButton';
const SuggestButton: FC<ContainedButtonProps> = ({ onClick, ...restProps }) => type SuggestButtonOptionalProps = {
onClick ? ( show?: boolean;
};
type SuggestButtonProps = ContainedButtonProps & SuggestButtonOptionalProps;
const SUGGEST_BUTTON_DEFAULT_PROPS: Required<SuggestButtonOptionalProps> = {
show: true,
};
const SuggestButton: FC<SuggestButtonProps> = ({
onClick,
show: isShow = SUGGEST_BUTTON_DEFAULT_PROPS.show,
...restProps
}) =>
isShow ? (
<ContainedButton {...{ onClick, tabIndex: -1, ...restProps }}> <ContainedButton {...{ onClick, tabIndex: -1, ...restProps }}>
Suggest Suggest
</ContainedButton> </ContainedButton>
@ -11,4 +25,6 @@ const SuggestButton: FC<ContainedButtonProps> = ({ onClick, ...restProps }) =>
<></> <></>
); );
SuggestButton.defaultProps = SUGGEST_BUTTON_DEFAULT_PROPS;
export default SuggestButton; export default SuggestButton;

Loading…
Cancel
Save