form을 통해서 여러가지 값 상태들을 바꾸는 것을 알아보자!
useState를 한 개 쓰는 것은 이제 알았다. useState를 통해서 prop 하나를 바꾸는 방법은 알게 되었는데, 그렇다면 여러개를 한번에 바꿀수는 없을까? 여러개를 한꺼번에 바꾸지 못하면 바꾸고 싶은 값을 다 일일이 useState를 통해 선언해줘야 하는데, 너무 비효율적이지 않은가!! 심지어 한 개의 form안에서 작동하는 매우 접근성이 강한 애들인데 말이다.
👉 이럴 때 해결방법은, 객체를 이용하는 것이다.
아 뭐, 너무 간단하네! 라고 생각한 나에게 주어진 것은..
🤔 이정도면 뭐, 무슨일이 일어나고 있는거 거의 통째로 이해 못했다고 할 수 있다. ^ ^
그래 아무것도 아니야. 에러는 배울 수 있는 좋은 기회일 뿐....ㅎ.ㅎ 다시 마음을 다잡고 하나하나 차근차근 이해하며 살펴보았다.
```jsx
const [contact, setContact] = useState({
fName: "",
lName: "",
email: ""
});
```
🛑 여기서 기억할 점 하나! return문 안에 있기 때문에 우리는 jsx문법을 사용중이다.
jsx문법에서 javascript를 사용하려면 {} curly bracket 안에 값을 넣어주어야 하며, 우리는 객체의 각각 key에 해당하는 value를 가져올 것이기 때문에 “.” dot notation을 통해 가져오고 있으며, jsx 문법이기에 띄어쓰기가 그대로 적용된다.
```jsx
<h1>
Hello {contact.fName} {contact.lName}
</h1>
```
```jsx
function handleChange();
<input onChange={handleChange} name="fName" placeholder="First Name" value={contact.fName}/>
<input onChange={handleChange} name="lName" placeholder="Last Name" value={contact.lName}/>
<input onChange={handleChange} name="email" placeholder="Email" value={contact.email}/>
```
🛑 주의 1. destructuring 문법을 이용해준다.
const name = [event.target](http://event.target).name; const value = event.target.value
를 살펴보면, event.target 객체의 property를 사용하고 있는 것을 알 수 있다. 객체를 destructuring 문법으로 작성하려면 {}안에서 분해하면된다.
🛑 주의 2. 여러 값들을 반환하려면 object나 array형태로 만들어 반환해야 한다는 것을 기억!
setContact에는 함수가 들어있고 그 함수는 조건에 따라서 세 가지 값을 바꿔야 하는 상황이다. 우리는 이걸 위해 이미 사전에 contact를 객체로 만들어주었고, 객체를 반환하는 것이기 때문에 모든 값들을 {}안에 묶어서 반환하고 있다. return {}
🤯 순간 return문인데 왜 {}로 묶나 헷갈렸었다. 정신차려 이친구야...
Returning Multiple Values from a Function
🛑 주의 3. prevValue
로 이전 값을 잡아놔야한다!! 그리고prevValue는 이전 state, 객체! 그러니까 값을 하나하나 사용하고 싶다면 . notation 사용!
지금 하나의 state를 객체 형태로 움직이고 있는 것이다. 따라서 새로운 event가 일어날 때마다 rendering이 다시되고 있다는 것을 떠올려보면 된다. 실제로 개발자 도구를 열어서 보면, 우리가 값 하나하나 입력할 때마다 이전 state는 사라지고 새롭게 rendering이 되면서 초기값 → 우리가 입력한 값으로 변경되는 것을 확인할 수 있다. 즉, 이전에 내가 fName에다가 뭐라고 썼든간에, lName에다가 새로 입력하면 다시 fName은 초기 상태인 “”로 입력이 되면서 화면에서 값이 사라지는 것을 볼 수 있다.
function handleChange(event){
const {name, value} = event.target;
setContact(prevValue => {
if(name === "fName"){
return {
fName : value,
lName : prevValue.lName,
email : prevValue.email,
}
}else if(name === "lName"){
return {
fName : prevValue.fName,
lName : value,
email : prevValue.email,
}
}else if(name === "email"){
return {
fName : prevValue.fName,
lName : prevValue.lName,
email : value,
}
}
})
```jsx
value={contact.fName}
value={contact.lName}
value={contact.email}
```
import React, { useState } from "react";
function App() {
const [contact, setContact] = useState({
fName: "",
lName: "",
email: ""
});
function handleChange(event){
const {name, value} = event.target;
setContact(prevValue => {
if(name === "fName"){
return {
fName : value,
lName : prevValue.lName,
email : prevValue.email,
}
}else if(name === "lName"){
return {
fName : prevValue.fName,
lName : value,
email : prevValue.email,
}
}else if(name === "email"){
return {
fName : prevValue.fName,
lName : prevValue.lName,
email : value,
}
}
})
}
return (
<div className="container">
<h1>
Hello {contact.fName} {contact.lName}
</h1>
<p>{contact.email}</p>
<form>
<input onChange={handleChange} name="fName" placeholder="First Name" value={contact.fName}/>
<input onChange={handleChange} name="lName" placeholder="Last Name" value={contact.lName}/>
<input onChange={handleChange} name="email" placeholder="Email" value={contact.email}/>
<button>Submit</button>
</form>
</div>
);
}
export default App;
⭐️ 그런데 의문이 든다..중간에 return 값을 계속 반복해서 똑같은거를 작성하고 있는데, 더 간단한 방법 없을까? 분명히 있을 것 같다 분명히 만들었을 것 같은 느낌적인 느낌이 매우 강하게 치솟는다!!
스프레드 연산자는 배열, 함수 parmeter, 객체에서 사용할 수 있다.
1) 배열
을 병합, 복사할 수 있다.
2) 함수
의 rest parameter로 사용하거나, 호출 인자로 사용할 수 있다.
3) 객체
복사 또는 업데이트에 사용할 수 있다.
const citrus = ["Lime", "Lemon", "Orange"];
const fruits = ["Apple", "Banana", "Coconut", ...citrus]
console.log(fruits);
// ["Apple", "Banana", "Coconut", "Lime", "Lemon", "Orange"]
// 😃 Without Spread Operator, the original array CAN BE CHANGED
const arr1 = ['민주', '민주2'];
const arr2 = arr1;
arr2.push = '민주3'
console.log(arr1);
// ['민주', '민주2', '민주3'];
// 😃 With Spread Operator, the original array CAN NOT be CHANGED - 얕은복사수행!
const arr1 = ['민주', '민주2'];
const arr2 = [...arr1];
arr2.push = '민주3'
console.log(arr1); // ['민주', '민주2'] 원본 배열은 변경되지 않는다.
console.log(arr2); // ['민주', '민주2', '민주3'];
파라미터로 오는 애들을 잡아서 ‘배열'에 집어넣는다.
function add(...rest){
let sum = 0;
for(let item of rest){
sum += item;
}
return sum
}
console.log(add(1)); // 1
console.log(add(2,3); // 5
console.log(add(2,3,4,5); // 14
const numbers = [1,4,2,5];
Math.min(...numbers);
const myName = { fName: "민주", lName: "김" };
myName = {...myName, gender:"female"};
console.log(myName); // {fName: "민주", lName: "김", gemder: "female"}
const myName = { fName: "민주", lName: "김" };
myName = {...myName, fName: "영희", gender:"female"};
console.log(myName); //fName: "영희", lName: "김", gender:"female"
아까 그 예시로 돌아와서! Spread 연산자를 이용해서 코드를 줄여보자!
function handleChange(event){
const {name, value} = event.target;
setContact(prevValue => {
return {
...prevValue,
[name]: value
}
})
}
🛑 주의할 점! 나는 정의해 놓은 name을 가져와서 key로 사용하고 싶기 때문에 이럴 경우 [ ] bracket notation을 사용해서 작성해 주어야 한다. 만약 그냥 name이라고 작성하면 키의 값이 name인, 일반적인 key:value를 작성하는 구문이 되어 버린다.
자바스크립트 기본 문법이 매!!우!! 중요하다.
코드가 어떻게 돌아가는지 자!!세!!히!! 살펴보고 정!!확!!히!! 이해하자.