Form์ ์ ์ฅํ ๋ ํ์ํ input ์ํ๊ฐ์ object ํ์ ์ผ๋ก ํ๋ฒ์ ๊ด๋ฆฌํ๊ณ , ๊ฐ input ๊ฐ์ด ๋ณ๋๋ ๋๋ง๋ค ์์ ๋ถ๋ชจ์์ handleChange ํจ์๋ฅผ ํธ์ถํ์ฌ form ์ํ๊ฐ์ ์ผ๊ด์ ์ผ๋ก ๊ด๋ฆฌํ๋ค.
์์ ๋ถ๋ชจ๋ ์ํ๊ฐ ๊ด๋ฆฌ ๋ฐ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๊ณ , ํ์ ์ปดํฌ๋ํธ๋ ์์์์ ์ํ๊ฐ์ ๋ฐ์ ui ๋ง ๊ทธ๋ฆด ์ ์๋๋ก ๊ด์ฌ์ฌ๋ฅผ ๋ถ๋ฆฌํ์๋ค.
๊ธฐ๋ณธ์ ์ธ ์ค๊ณ๋ ์์ ์ค๋ช ๊ณผ ๊ฐ์ด ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ๋ ค๊ณ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ๋๋ฐ ์ด์ ์ ๋ง์ถ์๋๋ฐ, ๋ญ๊ฐ ๋ฌธ์ ๊ฐ ์์๋ค.
์์ ๋ถ๋ชจ ์ปดํฌ๋ํธ
export const Form = () => {
const initialFormValue: Info = {
name: '',
location: {
address: '',
detailAddress: '',
zipCode: '',
latitude: 0,
longitude: 0,
},
isGroup: false,
};
const [formValue, setFormValue] = useState<Info>(initialFormValue);
const handleChangeFormValue = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, checked } = e.target;
if (e.target.type === 'checkbox') {
setFormValue({
...formValue,
isGroup: checked,
});
} else {
setFormValue({
...formValue,
[name]: value,
});
}
};
const handleCreateInfo = (inputs: Info) => {
//์์ฑ api๋ฅผ ์๋ฒ์ ์์ฒญ
};
const handleSave = () => {
handleCreateInfo(formValue);
};
return (
<>
<BasicInfoForm
formValue={formValue}
onChangeFormValue={handleChangeFormValue}
/>
<Box display={'flex'} justifyContent={'flex-end'} gap={2}>
<Button onClick={handleCancel}>
์ทจ์
</Button>
<Button onClick={handleSave}>
์ ์ฅ
</Button>
</Box>
</>
);
};
ํ์ ์์ ์ปดํฌ๋ํธ
interface Props {
formValue: Info;
onChangeFormValue: (e: React.ChangeEvent<HTMLInputElement>) => void;
}
export const BasicInfoForm = (props: Props) => {
const { formValue, onChangeFormValue } = props;
const { siteName, phone, location } = formValue;
return (
<Grid container border={'solid 1px'} mb={3}>
<Typography>์ด๋ฆ</Typography>
<TextField
placeholder='์ด๋ฆ์ ์
๋ ฅํ์ธ์'
name='name'
value={name}
onChange={onChangeFormValue} />
<Typography>์ ํ๋ฒํธ</Typography>
<TextField
name='phone'
value={phone}
onChange={onChangeFormValue} />
<Typography>๊ทธ๋ฃน ์ค์ </Typography>
<FormGroup>
<FormControlLabel
control={
<Checkbox
checked={isGroup}
onChange={onChangeFormValue}
/>
}
/>
</FormGroup>
</Grid>
);
};
(์ฃผ์ Textfield๋ ์ด ์ปดํฌ๋ํธ์์๋ ๋์ผํ ๋ฐ๋ณต์ด๋ฏ๋ก ์๋ต )
์ ์์ ์ฝ๋๋ฅผ ์ธ๋ถ์ ์ผ๋ก ๋ณด์!
interface Info {
name: string;
location: {
address: string;
detailAddress: string;
zipCode: string;
latitude: number;
longitude: number;
},
isGroup: boolean;
phone?: string
};
const [formValue, setFormValue] = useState<Info>(initialFormValue);
์์ ์ปดํฌ๋ํธ์์ `formValue`๋ผ๋ ์ํ๊ฐ์ผ๋ก ์ด๋ฆ, ์ฃผ์, ์ ํ๋ฒํธ, ๊ทธ๋ฃน์ค์ ์ฌ๋ถ ๋ฐ์ดํฐ๋ฅผ Info๋ผ๋ ํ์ ์ ๊ฐ์ฒดํํ๋ก ๊ด๋ฆฌํ๋ค.
const handleChangeFormValue = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, checked } = e.target;
if (e.target.type === 'checkbox') {
setFormValue({
...formValue,
isGroup: checked,
});
} else {
setFormValue({
...formValue,
[name]: value,
});
}
};
๊ทธ๋ฆฌ๊ณ ์ด `formValue`๋ผ๋ ์ํ๋ฐ์ดํฐ๋ ์ํ๋ฅผ ๋ณ๊ฒฝํด์ฃผ๋ ํจ์`handleChangeFormValue` ๋ฅผ ํธ์ถํ๋ฉด์ ๊ฐ ์ด๋ฆ,์ฃผ์ ๋ฐ์ดํฐ ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ค.
์ฌ๊ธฐ์ ์ค์ ์ ์ ์ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ ์ธํ ์ปดํฌ๋ํธ, ์ฒดํฌ๋ฐ์ค ์ปดํฌ๋ํธ๋ ํ์์ ์๊ณ , ์์ ๋ถ๋ชจ์์ ํด๋น ํ๋กํผํฐ์ ์ํ๊ฐ์ ๋ณ๊ฒฝ์์ผ์ผํ๊ธฐ ๋๋ฌธ์ ํ์ ์ปดํฌ๋ํธ์ ์ด๋ฒคํธ๋ฅผ ๋ถ๋ชจ์์ ์์์ผ ๋๋ค๊ณ ์๊ฐํ๋ค.
๊ทธ๋์ ๋ฐ์์ค๋ event ํ๊ฒ์ ์ด๋ฆ(`name`, `phone`, ...)์ ๋ฐ๋ผ event.target.value๋ฅผ ๋ณ๊ฒฝ์์ผ์ฃผ๋๋ก ์์ ๋ถ๋ชจ์์ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ์์ฑํด์ฃผ์์๋ค.
๊ทธ๋ฐ๋ฐ ์ด ์ฝ๋์๋ ์ด๋ฐ ๋ฌธ์ ์ ์ด ์๋๋ฐ...
๊ธฐํ์ด ๊ณ ๋ํ๋์ด ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋์ด form์์ ์๋ก์ด ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด์ submitํด์ผํ๋ ์ํฉ์ด ์๋ค๊ณ ํ์. `Info` ํ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๋ฐ์ดํฐ์์ ๋ฐฐ์ด ํ์ ์ ๊ฐ์ง ๊ทธ๋ฃน ๋ฐ์ดํฐ๋ ์ถ๊ฐํด์ผ ๋๋ค.
interface Info {
...๋์ผ
groups: string[]
}
`groups` ํ๋กํผํฐ๋ก ๊ด๋ฆฌํ๋ ๊ทธ๋ฃน ๋ฐ์ดํฐ๋ ui๋ฅผ ์๋์์ฑ ๊ฒ์ ์ปดํฌ๋ํธ ๊ตฌํํ๋๋ฐ, ์ด ๊ฒ์ ์ปดํฌ๋ํธ๋ onChange ์ด๋ฒคํธ๋ก ๋ค๋ฅธ ์ด๋ฒคํธ ํ์ ๊ณผ ์ถ๊ฐ์ ์ธ ์ธ์๋ฅผ ํ์๋ก ํ๋ค.
๋ถ๋ชจ์์๋ ํธ๋ค์ฒด์ธ์ง ํจ์์ ์ธ์๋ก e: React.ChangeEvent๋ฅผ ๋ฐ๋ ๋ฐ๋ฉด์, ํ์ ์์์ธ ์๋์์ฑ ์ปดํฌ๋ํธ๋ ํจ์์ ์ธ์๋ก React.SyntheticEvent์ newArr๋ผ๋ ์๋ก์ด ๋ฐฐ์ด๊น์ง ๋ ๊ฐ์ง์ ์ธ์๋ฅผ ๋ฐ๋๋ค.
const handleChangeFormValue = (e: React.ChangeEvent<HTMLInputElement>) => {...}
const handleChangeAutoComplete = (e: React.SyntheticEvent, newArr: string[]) => {...}
๊ทธ๋์, ์๋์์ฑ ์ปดํฌ๋ํธ๋๋ฅผ ์ถ๊ฐํ๋ค๋ฉด ์์๋ถ๋ชจ์ `handleChangeFormValue`ํจ์๋ก ์ผ๊ด์ ์ผ๋ก ๋ฐ์ดํฐ ๋ณ๊ฒฝ์ ์ฒ๋ฆฌํ ์ ์๋ค๋ ๋ฌธ์ ์ ์ด ๋๋ฌ๋ฌ๋ค.
์๋
์ด๋ ๊ธฐ์ ๊ณ ๋ฏผ๋์ `์๋์์ฑ์ ์ํ๊ฐ์ ๊ด๋ฆฌํ๋ ๋ฐฐ์ด`์ ๋ฐ๋ก ๋ถ๋ชจ์ ์ถ๊ฐํด์ ํ์ ์์ ์๋์์ฑ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ค. ๊ทธ๋ฐ๋ฐ, ์ด ๊ฒฝ์ฐ ์๋์์ฑ์ ํด๋นํ๋ ์ํ๋ formValue ์ํ์ ๋ฐ๋ก ๋ ๋ฆฝ์ ์ผ๋ก ์๋ํ๋ค. ๊ทธ๋ ๊ธฐ์ form์ submit ํ๋ ์ ์ฅ์์ ๊ทธ `formValue`์ `์๋์์ฑ ๋ฐฐ์ด Value` ๋ ๊ฐ์ง๋ฅผ ํฉ์ณ์ ์๋ฒ์ ์ ์ฅํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌํํ๋ ๊ฒ์ผ๋ก ํด๊ฒฐํ๋ค.
ํ์ง๋ง ์์ ๊ฐ์ ํด๊ฒฐ์ฑ ์ ๋น์ฅ ๊ธํ ๋ถ์ ๋ workaround์ ๋ถ๊ณผํ๋ค. ์๋๋ฉด?
- `HTMLInputElement` ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค์ง ์๋ ์ปดํฌ๋ํธ๋ ๋ถ๋ชจ์ ํธ๋ค์ฒด์ธ์ง ํจ์๋ก ์ ์ดํ ์ ์์ด, ๋ถ๋ชจ์ change ํจ์์์ ๋ชจ๋ ์ํ๊ฐ์ ์ ์ดํ๊ณ ์ ํ๋ ์๋๋ก ํ๋ ๋ฆฌํฉํ ๋งํ ์๋ฏธ๊ฐ ์์ด์ง๋ค.
- ๋, ๋ฐ๋ก ์ํ๊ฐ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์๋ Autocomplete์ ui๋ผ๋ ๋ณ๊ฒฝ๋๋ฉด ๊ทธ ์ํ๋ฅผ ๋ฐ๋ก ๊ด๋ฆฌํ๊ณ ์๋ ๊ณณ์ ์ฐพ์์ ๋ ๋ค ์์ ํด์ค์ผ ํ๋ ๋ฌธ์ ์ ์ด ์์ ์ ์๋ค.
๋ฆฌํฉํ ๋ง
๋ถ๋ชจ์์ ์ผ๊ด์ ์ผ๋ก ์์ ์ํ๋ฅผ ๋ณ๊ฒฝ์ํค๊ณ ์ถ์ผ๋ฉด change ํจ์๋ฅผ ๋ณ๊ฒฝํ ํ์๊ฐ ์๋ค.
์ฌ๊ธฐ์ ๋ถ๋ชจ๋ ์์์ ์ด๋ฒคํธ ์ ๋ณด๋ฅผ ์ ํ์๊ฐ ์๋ค.
`์ด๋ฒคํธ๋ ๊ฐ ์์ ์ปดํฌ๋ํธ์์` (์ธํ์ด๋ ์ฒดํฌ๋ฐ์ค๋ ์๋์์ฑ์ด๋) ์ด๋ฒคํธํธ๋ค๋ฌ๋ก ํธ์ถํ๊ณ , ๋ถ๋ชจ์ change ํจ์ ๋งค๊ฐ๋ณ์์๋ event ์ ๋ณด๊ฐ ์๋ ์๋ก ๊ฐฑ์ ํ๊ณ ์ ํ๋ ๊ฐ์ ํด๋น ํ๋กํผํฐ๋ฅผ ํค๊ฐ์ผ๋ก ํ๋ ๊ฐ์ฒด ํํ๋ก ์ ์ด์ค๋ค.
const handleChangeFormValue = (newValue: Partial<Info>) => {
setFormValue({...formValue, ...newValue });
};
์ด๋ ๊ฒ ์ ์ด์ฃผ๋ฉด ๋ถ๋ชจ์์ ์์์ปดํฌ๋ํธ์ ์ฐ๊ฒฐ๋ ์ํ๊ฐ์ ํ๋์ ํจ์๋ก ์ ์ดํ ์ ์๊ฒ๋๋ค.
์ฝ๋๋ ๋จ 3์ค๋ก ์ค์ด๋ค์๋ค.
์ด๋ฆ ์ปดํฌ๋ํธ
<TextField
value={name}
onChange={(e) =>
onChangeFormValue({ name: e.target.value })
} />
ํ์ ์์์ ์๋ ์ปดํฌ๋ํธ์์ onChange ์ด๋ฒคํธ๋ฅผ ๋ฐ์ธ๋ฉํด ํด๋น ์ปดํฌ๋ํธ์์ ๋ฐ์ํ๋ ์ด๋ฒคํธ ๋ฐธ๋ฅ๊ฐ์ ์ธ์๋ก ๋ฐ์ ์์์์ props๋ก ๋๊ฒจ๋ฐ์ `onChangeFormValue` ํจ์๋ฅผ ํธ์ถํด์ค๋ค.
์ฒดํฌ๋ฐ์ค ์ปดํฌ๋ํธ
<FormGroup>
<FormControlLabel
control={
<Checkbox
checked={isGroup}
onChange={(e) =>
onChangeFormValue({ isGroup: e.target.checked })
}
/>
}
/>
</FormGroup>
์ฒดํฌ ๋ฐ์ค๋ ๋ง์ฐฌ๊ฐ์ง.
์ฒดํฌ๋ฐ์ค๋ฅผ ๋๋ฌ์ ๋ฐ๋ ์ด๋ฒคํธ ๊ฐ์ event.target.checked ๊ฐ์ผ๋ก ์ ์ ์์ผ๋ { ํด๋น ํ๋กํผํฐ : ์ด๋ฒคํธ ๊ฐ } ์ ์ธ์๋ก ๋๊ฒจ์ฃผ์ด ์์์์ ๊ด๋ฆฌํ๊ณ ์๋ `FormValue` ์ํ๊ฐ์ด ๋ณ๊ฒฝ๋๊ฒ ํ๋ค.
๋ฆฌํฉํ ๋งํ๋๋ผ ์ฌ๋ฐ์๋ค!!!!
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์ด๋ฏธ์ง ๋ฆฌ์คํธ FCP First Contentful Paint ์ฑ๋ฅ ๊ฐ์ (0) | 2024.03.08 |
---|---|
vite public html ํ์ผ iframe์ผ๋ก ๋์ฐ๊ธฐ (0) | 2024.02.21 |
debounce๋ก ์ค์๊ฐ ๊ฒ์์ด api ํธ์ถ ์ค์ด๊ธฐ (0) | 2024.02.07 |
Typescript + React ์กฐ๊ฑด๋ถ props ์ ๋ฌํ๊ธฐ - discriminated unions (0) | 2024.02.05 |
failed to resolve entry for package monorepo (0) | 2024.01.23 |