✅ 중복 코드 리팩토링
앞서 만들었던 사용자 입력을 관리하던 코드에는
중복된 코드가 많다.
이런 경우에는 코드를 보다 간결하게 작성해서 관리할 수 있다.
먼저 기존 코드를 살펴보자.
import { useState } from "react";
const Register = () => {
const [name, setName] = useState("");
const [birth, setBirth] = useState("");
const [country, setCountry] = useState("");
const [bio, setBio] = useState("");
const onChangeName = (e) => {
setName(e.target.value);
};
const onChangeBirth = (e) => {
setBirth(e.target.value);
};
const onChangeCountry = (e) => {
setCountry(e.target.value);
};
const onChangeBio = (e) => {
setBio(e.target.value);
};
return (
<div>
<div>
<input value={name} onChange={onChangeName} placeholder="이름" />
</div>
<div>
<input value={birth} onChange={onChangeBirth} type="date" />
</div>
<div>
<select value={country} onChange={onChangeCountry}>
<option></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
{country}
</div>
<div>
<textarea value={bio} onChange={onChangeBio} />
</div>
</div>
);
};
export default Register;1. 공통 state 묶기
먼저, 각각 따로 상태를 관리하던 state를
하나의 객체로 묶어 관리할 수 있도록
기존 코드를 삭제하고 리팩토링해보자.
const [name, setName] = useState("");
const [birth, setBirth] = useState("");
const [country, setCountry] = useState("");
const [bio, setBio] = useState("");const [input, setInput] = useState({
name: "",
birth: "",
country: "",
bio: "",
});2. 이벤트 핸들러 수정
더 이상 존재하지 않는 함수를 삭제하고
공통으로 사용되는 상태 변경 함수를 활용하자.
먼저,
name 프로퍼티의 값을 변경할 함수를 작성하자.setInput 함수를 사용하여 name 프로퍼티의 값을e.target.value 값으로 변경하자.const onChangeName = (e) => {
setInput({
name: e.target.value,
});
};하지만 여기까지만 적으면 굉장히 위험한 코드가 된다.
해당하는 이벤트가 발생했을 때
name 값이 변경되며다른 프로퍼티의 값이 전부 날아갈 수 있기 때문이다.
따라서 작성해두었던 코드 위에
전개연산자를 사용해
input에 있던 기존 값을 뿌려주어야 한다.const onChangeName = (e) => {
setInput({
...input,
name: e.target.value,
});
};input의 값을 미리 뿌려주는 이유는,해당하는 이벤트 핸들러가 실행됐을 때,
변경하고자 하는 값 외에 기존에 있던 값을
넣어주기 위함이다.
해당하는 정보를 미리 뿌려주지 않으면
이벤트가 실행될 때 다른 프로퍼티의 값은
사라지고 name 프로퍼티만 남게되기 때문이다.
마찬가지로 다른 이벤트 핸들러도 수정해주자.
const onChangeName = (e) => {
setInput({
...input,
name: e.target.value,
});
};
const onChangeBirth = (e) => {
setInput({
...input,
birth: e.target.value,
});
};
const onChangeCountry = (e) => {
setInput({
...input,
country: e.target.value,
});
};
const onChangeBio = (e) => {
setInput({
...input,
bio: e.target.value,
});
};3. value 변경
기존에
value에 넣어두었던 변수는 더 이상 존재하지 않는다.따라서 input객체에 프로퍼티로 존재하는 이름으로 변경해주자.
return (
<div>
<div>
<input value={input.name} onChange={onChangeName} placeholder="이름" />
</div>
<div>
<input value={input.birth} onChange={onChangeBirth} type="date" />
</div>
<div>
<select value={input.country} onChange={onChangeCountry}>
<option></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
</div>
<div>
<textarea value={input.bio} onChange={onChangeBio} />
</div>
</div>
);
};이제, 상태가 잘 저장되고 있는 지 확인하기 위해
console에
input객체를 출력해보자.const [input, setInput] = useState({
name: "",
birth: "",
country: "",
bio: "",
});
console.log(input);사용자 입력에 따라 저장되고 있는 것을 확인할 수 있다.

4. 통합 이벤트 핸들러 만들기
이벤트 핸들러도 모두 같은 코드를 가지고 있어
이를 통합하여 사용할 수 있다.
합성 이벤트 객체에서 제공하는
e.target.name이라는 속성을 활용할 수 있다. const onChange = (e) => {
setInput({
...input,
[e.target.name]: e.target.value,
});
};하지만 합성 이벤트 객체에서 제공하는
name은수기로 입력하지 않으면 기본값이 빈문자열로
제공되기 때문에 각 입력폼에
name 속성을작성해주어야한다.
return (
<div>
<div>
<input
name="name"
value={input.name}
onChange={onChange}
placeholder="이름"
/>
</div>
<div>
<input
name="birth"
value={input.birth}
onChange={onChange}
type="date"
/>
</div>
<div>
<select name="country" value={input.country} onChange={onChange}>
<option></option>
<option value="kr">한국</option>
<option value="us">미국</option>
<option value="uk">영국</option>
</select>
</div>
<div>
<textarea name="bio" value={input.bio} onChange={onChange} />
</div>
</div>
);Share article