useState
가 어느 정도 익숙해진 것 같으니(?) 좀더 심화적인 내용을 다뤄볼까 한다. 바로 이름부터 낯선 계산된 속성명이라는 개념인데 이것이 무엇이고 어떻게 쓰이는지 살펴보도록 하자!
계산된 속성명이란 ES6부터 지원되는 기능으로 객체의 속성명이 최초에 결정되는 것이 아니라 동적으로 결정되는 것을 말한다. 이때 객체에 접근을 할때는 dot notation이 아니라 []
을 사용한다.
// 계산된 속성명 미사용
const before = (name, value) => {
const obj = {};
obj[name] = value;
return obj;
}
// 계산된 속성명 사용
const after = (name, value) => {
return {[name]: value} //계산된 속성명 [name]
//[name]값이 name의 이름으로 동적으로 할당됨
}
name
이라는 매개변수를 통해서 return안에 [name]이 동적으로 계산되면서 상황에 맞게 들어가는 것을 알 수 있다. []
를 사용하지 않으면, name
에 들어오는 인자가 아닌 name
이라는 이름을 가진 프로퍼티에 value
가 할당되기 때문에 원하는 대로 동작하지 않을 것이다! input
값은 useState
를 통해서 상태 관리가 이루어졌다. 여기서 만약 input
이 여러개라면 각각에 해당하는 state
를 생성해줘야 할 것이다.
//수정 전
import { useState } from "react";
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassWord] = useState("");
const saveUserEmail = e => {
setEmail(e.target.value);
};
const saveUserPassword = e => {
setPassWord(e.target.value);
};
return (
<div className="login">
<div className="container">
<h1 className="logo">Instagram</h1>
<form>
<input
type="text"
name="email"
placeholder="이메일"
onChange={saveUserEmail}
/>
<input
type="password"
name="password"
placeholder="비밀번호"
autoComplete="on"
onChange={saveUserPassword}
/>
<button className="login-btn">로그인</button>
</form>
</div>
<div className="container sm">
<p>
계정이 없으신가요?
<button className="signup-btn">가입하기</button>
</p>
</div>
</div>
);
};
export default Login;
위의 코드 처럼 늘어난 input갯수 만큼 input을 관리하기 위한 state
와 onChange
함수를 생성할 것이다.
하지만 이는 좋은 방법이 아니다. input에 name
을 설정하고 이벤트가 발생했을 때 이 값을 참조하는 것이 코드의 가독성도 좋아지고 나중에 유지보수 관리도 수월 할 것이다.
하나의 state
로 input값들을 설정 할 수 있도록 위의 코드를 수정해보자!
// 수정 후
import { useState } from "react";
const Login = () => {
const [inputValue, setInputValue] = useState({
// 사용할 문자열들을 저장하는 객체 형채로 관리
email: "",
password: "",
});
const handleInput = (e) => {
const { name, value } = e.target;
setInputValue({ ...inputValue, [name]: value });
// name 키에 맞는 키값(value)를 가져온다. => 계산된 속성명
};
return (
<div className="login">
<div className="container">
<h1 className="logo">Instagram</h1>
<form>
<input
type="text"
name="email"
placeholder="이메일"
onChange={handleInput}
/>
<input
type="password"
name="password"
placeholder="비밀번호"
autoComplete="on"
onChange={handleInput}
/>
<button className="login-btn">로그인</button>
</form>
</div>
<div className="container sm">
<p>
계정이 없으신가요?
<button className="signup-btn">가입하기</button>
</p>
</div>
</div>
);
};
export default Login;
name
이라는 값을 설정하고 이벤트가 발생했을 때 그 값을 참조한다.useState
함수가 문자열을 관리해줬다면, 여기에서는 여러개의 문자열을 갖고 있는 객체 형태로 관리 해줘야한다.<input />
에 name을 속성을 부여 해줘야 하는데, onChange
함수에서 e.target.name
를 조회하면 변화된 값이 어떤 name인지 알 수 있다.state
를 만들어 주고 값이 바뀔 때 마다 객체 spread방식 ...inputValue
으로 값을 업데이트 해준다.💡 spread방식을 사용하는 이유
- 객체 상태를 업데이트 할 때는 꼭 기존의 상태를 한번 복사하고 나서 특정값을 덮어 씌우고 새로운 값을 설정 해주어야한다. 이것을 불변성을 지켜준다고 함. 이렇게 해야 리액트에서 업데이트 된 것을 감지하고 랜더링한다.
- 불변성 을 지켜줘야지만 나중에 컴포넌트 업데이트 성능을 최적화시켜줄 수 있다.
- spread 방식 사용 전
- spread 방식 사용 후
➡️ 사용전에는 전에 입력된 이메일 값이 초기화되어 없어지지만 사용후에는 입력값이 누적되어 새로운 값이 추가로 입력되는 것을 볼 수 있다.
마무리✨
여러 줄의 코드를 한줄로 줄이는 것에 쾌감을 느끼고 개발자는 게을러야 한다는 말을 오늘도 마음에 새기며 저는 마저 코딩하러 갑니다🥲