Skip to content

Commit

Permalink
refactor: Input 컴포넌트가 외부에서 값을 반영 및 maxLength 표기 이슈 개선
Browse files Browse the repository at this point in the history
  • Loading branch information
bytrustu committed Mar 26, 2024
1 parent cef6eae commit d6b3c94
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 30 deletions.
42 changes: 23 additions & 19 deletions src/shared/components/Input/FormatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type FormatInputContextValue = {
};

type FormatInputProps = Partial<FormatInputContextValue> & {
defaultValue: string[];
value: string[];
onValueChange?: (payload: { values: string[] }) => void;
onValueComplete?: (payload: { values: string[] }) => void;
};
Expand All @@ -49,7 +49,7 @@ const FormatInputContext = createContext<FormatInputContextValue | null>(null);

export const FormatInput = ({
id = '',
defaultValue,
value,
onValueChange,
onValueComplete,
type = 'alphanumeric',
Expand All @@ -62,22 +62,32 @@ export const FormatInput = ({
const formatFields = findComponentsInChildren(children, FormatField.name);
const inputElementCount = formatFields.length;

const { value: values, update: updateValue } = useInputFieldsValues(defaultValue, onValueChange, onValueComplete);
const inputFields = useInputFieldsValues(value, onValueChange, onValueComplete);
const inputRefs = useInputRefs(inputElementCount);

const contextValue = useMemo(
() => ({
id,
values,
values: inputFields.value,
updateValue: inputFields.update,
inputElementCount,
updateValue,
inputRefs,
type,
mask,
separator,
showCompletedSeparator,
}),
[id, values, inputElementCount, updateValue, inputRefs, type, mask, separator, showCompletedSeparator],
[
id,
inputFields.value,
inputFields.update,
inputElementCount,
inputRefs,
type,
mask,
separator,
showCompletedSeparator,
],
);

return (
Expand Down Expand Up @@ -151,6 +161,11 @@ const FormatField = ({
const validSeparator = index < inputElementCount - 1 && separator && index <= inputElementCount - 1;
const showSeparator = !showCompletedSeparator || (showCompletedSeparator && maxLength === inputValue?.length);

const [state, setState] = useState(0);
useEffect(() => {
setState(state + 1);
}, [inputValue]);

return (
<>
<TextField
Expand Down Expand Up @@ -203,22 +218,11 @@ const FormatInputTextCounter = ({ index, ...props }: PropsWithChildren<{ index:
const { inputRefs } = context;
const inputRef = inputRefs[index];

const [{ maxLength, currentLength }, setCounterState] = useState({
maxLength: 0,
currentLength: 0,
});
const currentLength = inputRef.current?.value.length ?? 0;
const maxLength = inputRef.current?.maxLength ?? 0;

const counterText = `${currentLength} / ${maxLength}`;

useEffect(() => {
if (inputRef.current) {
setCounterState({
maxLength: inputRef.current?.maxLength ?? 0,
currentLength: inputRef.current?.value.length ?? 0,
});
}
}, [inputRef]);

return (
<Typography variant="caption" color={styleToken.color.gray400} {...props}>
{counterText}
Expand Down
6 changes: 3 additions & 3 deletions src/shared/components/Input/PinInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type PinInputProps = PropsWithChildren<{
fontSize?: string;
fontWeight?: string;
placeholder?: string;
defaultValue?: string[];
value?: string[];
onValueChange?: (details: { values: string[] }) => void;
onValueComplete?: (details: { values: string[] }) => void;
}>;
Expand All @@ -45,15 +45,15 @@ export const PinInput = ({
type = 'numeric',
mask = false,
placeholder = '*',
defaultValue = [],
value = [],
onValueChange,
onValueComplete,
children,
}: PropsWithChildren<PinInputProps>) => {
const formatFields = findComponentsInChildren(children, PinInputField.name);
const inputElementCount = formatFields.length;

const { value: values, update: updateValue } = useInputFieldsValues(defaultValue, onValueChange, onValueComplete);
const { value: values, update: updateValue } = useInputFieldsValues(value, onValueChange, onValueComplete);
const inputRefs = useInputRefs(inputElementCount);

const contextValue = useMemo(
Expand Down
7 changes: 1 addition & 6 deletions src/shared/components/Input/hooks/useInputFieldsValues.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
import { useState } from 'react';
import { UpdateValueProps } from '@/shared';

const validateComplete = (values: string[], maxLength?: number) =>
values.every(Boolean) && values.every((value) => value.length === maxLength);

export const useInputFieldsValues = (
defaultValue: string[],
values: string[],
onValueChange?: (payload: { values: string[] }) => void,
onValueComplete?: (payload: { values: string[] }) => void,
) => {
const [values, setValues] = useState(defaultValue);

const updateValue = ({ index, value, inputRefs, maxLength, focus = true }: UpdateValueProps) => {
const newValues = [...values];
newValues[index] = value;
setValues(newValues);

onValueChange?.({ values: newValues });

if (validateComplete?.(newValues, maxLength)) {
Expand Down
13 changes: 11 additions & 2 deletions src/shared/components/Input/hooks/useInputValues.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { useState } from 'react';

export const useInputValues = (initialValues: string[]) => {
export const useInputValues = (
initialValues: string[],
options?: {
validate?: (values: string[]) => boolean;
transform?: (values: string[]) => string;
},
) => {
const [values, setValues] = useState<string[]>(initialValues);

const updateValues = ({ values }: { values: string[] }) => {
setValues(values);
};

return { value: values, update: updateValues };
const valid = options?.validate ? options.validate(values) : true;
const transformedValue = options?.transform ? options.transform(values) : values.join('');

return { value: values, transformedValue, valid, update: updateValues };
};

0 comments on commit d6b3c94

Please sign in to comment.