컴포넌트에서 보여야 하는 값이 사용자 인터랙션에 따라 바뀌어야 할 때를 고려해보자.
react v16.8 부터 Hooks 기능이 추가되면서, 함수형 컴포넌트일 때도 상태 관리를 할 수 있게 됐다. ✨
리액트 hooks 중 하나인 useState 함수를 배워보자
import React from 'react';
function Counter() {
const onIncrease = () => {
console.log('+1 button pressed');
}
const onDecrease = () => {
console.log('-1 button pressed');
}
return(
<div>
<h1>0</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
)
}
export default Counter;
버튼이 눌릴 때마다 로그가 잘 찍힌다.
이제 useState로 동적 관리를 해보자
const (변수명, 액션 함수) = useState(초기값);
const [number, setNumber] = useState(0);
number
라는 변수의초기값
은0
이고,
number를 바꾸는 함수
는setNumber
이다.
onIncrease와 onDecrease에 setNumber를 이용해준다.
//counter.js
import React, {useState} from 'react';
function Counter() {
const [number, setNumber] = useState(0);
const onIncrease = () => {
setNumber(number + 1);
}
const onDecrease = () => {
setNumber(number - 1);
}
return(
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
)
}
export default Counter;
이 때 useState를 함수 형태로 사용할 수도 있다.
// 전
const onIncrease = () => {
setNumber(number + 1);
}
// 후
const onIncrease = () => {
setNumber(prevNum => prevNum + 1);
}
이전 값을 가져와서 어떻게 변경할 지 정해준다.
컴포넌트를 최적화할 때 필요하다.
입력창에 문자를 입력하면, 실시간으로 값을 가져와줄 것이다.
//inputSample.js
import React, {useState} from 'react';
function InputSample(){
const [text, setText] = useState('');
// text 변수의 초기값 = ''
// text 변수 값 변경함수 = setText
const onChangefunc = (e) =>{
setText(e.target.value);
}
const oninit= () => {
setText('');
}
return(
<div>
<input onChange={onChangefunc} value={text}/>
<button onClick={oninit}>초기화</button>
<div>
<b>값: </b>
{text}
</div>
</div>
)
}
export default InputSample;
입력창의 값이 변화할 때마다 onChange
onChangefunc
함수가 실행된다.
‣ onChangefunc
함수를 통해 useState
로 만든 변수 text
의 값이 입력된 값으로 변경된다.
이때 매개변수는 아래와 같다.
e
: 상태가 변했을 때 이벤트에 대한 내용이 출력된다.e.target
: 현재 돔이 출력된다. :<input>
e.target.value
: 현재 돔에 담긴 값이 출력된다.
text
변수를 화면에 출력해주면 된다.
만약 input이 여러개 있을 땐, useState, onChange 를 여러개 선언하는 게 아니라, 객체
을 만들어서 참조하도록 하자.
<div>
<input
name="name"
placeholder="이름"
onChange={onChangefunc}
value={name}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChangefunc}
value={nickname}
/>
<button onClick={oninit}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
이름과 닉네임을 입력 받아 화면에 표시해줄 것이다.
const [inputs,setInputs] = useState({
//객체 형태로 상태관리
name: '',
nickname: '',
});
const { name,nickname } = inputs;
inputs
변수의 초기값은 {name: '', nickname: ''}
와 같이 객체 형태를 띈다.
name
, nickname
변수에 inputs
를 구조 분해 해준다.
변화가 발생할 때마다, onChangefunc가 호출된다.
e.target
에 수정된 객체의 name
과 수정된 값 value
가 담겨있다.
const onChangefunc = (e) =>{
const {name, value} = e.target
setInputs({
...inputs,
[name]: value,
});
};
🔥 리액트에선 객체를 update할 때, 기존의 객체를 복사해준 뒤 새로운 값을 덮어씌우는 형태로 진행해야 한다. 🔥
이 방법을 통해 불변성을 지킬 수 있고,
불변성을 지켜야만 리액트 컴포넌트에서 상태가 변한 것을 감지해서
필요한 렌더링만 할 수 있다.
정리
hooks인 useState 함수를 이용해 바뀌는 값을 관리할 수 있다.
import {useState} from 'react';
- 현재 상태를 바꾸는 함수의 인자에 변경할 값을 넣어주거나,
현재 값을 어떻게 바꿔줄지 함수를 넣어줄 수 있다.
onChange 함수는 인자 e를 리턴한다.
- e : 상태가 변했을 때 이벤트에 대한 내용이 출력된다.
- e.target : 현재 돔이 출력된다.
<input>
- e.target.value : 현재 돔에 담긴 값이 출력된다.
🔥불변성을 지켜서 객체를 업데이트 하기 위해선,
기존 객체를 복사한 뒤, 바뀐 값만 업데이트 하는 방식으로 하자!