[Next.js] EventHandler, useState 선언 및 수정, Array,Object state 변경
💡 EventHandler
<button onClick={()=>{ console.log(1) }}>버튼</button>
button 에 EventHandler 를 달아주려면 onClick={()=>{ JavaScript Code}} 이런 식으로 해야한다.
물론 client component 에서만 JavaScript 가 실행 가능하니까 페이지 상단에 'use client' 를 달아주자.
💡 useState
'use client'
import { useState } from "react";
export default function List() {
let [count, changeCount] = useState(0)
let products = ['Tomatoes', 'Pasta', 'Coconut']
return (
<div>
<h4 className="title">상품 목록</h4>
{
products.map((product, i) => {
return (
<div className="food" key={i}>
<img src={`/food${i}.png`} className="food-img"></img>
<h4>{products[i]} $40</h4>
<button onClick={()=>{changeCount(count-1)}}>-</button>
<span>{count}</span>
<button onClick={()=>{changeCount(count+1)}}>+</button>
</div>
)
})
}
</div>
);
}
변수를 선언하는 방법 이외에 useState 를 활용하는 방법도 있다.
🔧 useState 선언
1. 페이지 상단에 client component 선언
2. import { useState }
3. let [변수이름작명, 함수작명] = useState(변수에넣을값);
순서로 useState 를 설정해준다.
🔧 왜 변수 선언대신 useState 를 사용하는가?
일반 변수는 변경되어도 변수가 들어있는 html 에 자동으로 반영되지 않는다.
반면 state 가 변경되면 state 가 들어있는 html 도 자동으로 재렌더링 된다. ( html 을 지웠다가 다시 만든다. )
→ 자주 변경되는 값들만 useState 로 지정하면 좋다.
🔧 useState 수정
<button onClick={()=>{changeCount(count+1)}}>+</button>
EventListner={()=>{함수작명(JavaScript 를 활용해 변수이름작명 수정)}}
💡 Array, Object state 변경
'use client'
import { useState } from "react";
export default function List() {
let [count, changeCount] = useState([0, 0, 0])
let products = ['Tomatoes', 'Pasta', 'Coconut']
return (
<div>
<h4 className="title">상품 목록</h4>
{
products.map((product, i) => {
return (
<div className="food" key={i}>
<img src={`/food${i}.png`} className="food-img"></img>
<h4>{products[i]} $40</h4>
<button onClick={()=>{
let copy = [...count]
copy[i]--
changeCount(copy)
}}>-</button>
<span>{count[i]}</span>
<button onClick={()=>{
let copy = [...count]
copy[i]++
changeCount(copy)
}}>+</button>
</div>
)
})
}
</div>
);
}
상품이 3개니까 수량이 저장되어야할 곳도 3개가 필요해서 Array 를 사용했다.
이후에 onClick 안에 들어갈 함수를 설정했는데, 저 함수를 밖으로 빼냈다.
'use client'
import { useState } from "react";
export default function List() {
let [count, changeCount] = useState([0, 0, 0])
let products = ['Tomatoes', 'Pasta', 'Coconut']
// 수량 감소 함수
const decreaseCount = (index) => {
let copy = [...count];
copy[index]--;
changeCount(copy);
}
// 수량 증가 함수
const increaseCount = (index) => {
let copy = [...count];
copy[index]++;
changeCount(copy);
}
return (
<div>
<h4 className="title">상품 목록</h4>
{
products.map((product, i) => {
return (
<div className="food" key={i}>
<img src={`/food${i}.png`} className="food-img"></img>
<h4>{products[i]} $40</h4>
<button onClick={() => { decreaseCount(i)}}>-</button>
<span>{count[i]}</span>
<button onClick={() => {increaseCount(i)}}>+</button>
</div>
)
})
}
</div>
);
}
decreaseCount 와 increaseCount 함수를 보면 Array 를 copy 에 복사한 것을 볼 수 있다.
🔧왜그런가?
리액트의 동작 원리때문에 그렇다.
state변경함수() 를 쓰는 경우
컴퓨터는 기존state == 신규state 이렇게 먼저 검사를 해보고 같으면 state 변경을 하지 않는다.
안에 array 와 object 구성 요소를 바꿔도 state 변경이 되지 않을 것이다. 왜냐하면 javaScript 원리 상
1. 자바스크립트는 array/object 자료를 하나 만들면
예를 들어서 let arr = [1,2,3] 이렇게 만들면
[1,2,3] 자료는 RAM이라는 공간에 몰래 저장이 되고
let arr 변수엔 그 자료가 어디있는지 가리키는 화살표만 담겨있다.
2. array/object 자료를 수정한다고 해도
화살표타고 들어가서 RAM에 있던 값이 수정될 뿐
변수에 담긴 화살표는 변하지 않는다.
그래서 아까 기존state == 신규state 비교하면 같다고 나오는 것이다.
(==로 비교하면 변수에 저장된 값인 화살표만 비교해줍니다)
3. 심지어 array/object 자료를 복사해도 화살표만 복사된다.
let copy = [...수량]
수량[0]++
수량변경(copy)
때문에 완전한 복사본을 뜻하는 [...수량]
을 이용해 복사본을 만들어 주면 아예 별개의 array 또는 object 가 되기 때문에 화살표도 다르게 된다.
그래서 state 가 변경된다.