리액트를 사용하여 버튼을 클릭하면 숫자가 증가하는 웹 페이지를 만들어보자.
✅ counter 변수와 render 함수 사용
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
let counter = 0;
function countUp() {
counter = counter + 1;
render();
}
function render() {
ReactDOM.render(<Container />, root);
}
const Container = () => (
<div>
<h3>Total click: {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
render();
</script>
</html>
위의 코드를 통해 Container라는 컴포넌트를 만들고 render 함수를 통해 Container를 root 안에 그린다.
Container 안에는 button이 존재하고 이 button을 클릭했을 때 countUp이라는 함수가 실행된다.
countUp은 let으로 선언된 counter를 하나 증가시키고 다시 render 함수를 불러 화면을 다시 그린다.
🚨 문제
여기서 문제는 변하는 무언가가 있을 때마다 render라는 함수를 호출해줘야 변화된 것이 새로 화면에 그려진다.
즉, 모든 변화 끝에는 render 함수를 호출해야 하는 안좋은 코드인 것이다.
✅ React.useState
이를 해결하기 위해 React.useState를 사용한다.
State란 리액트에서 객체이며 변수로 활용된다.
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
const Container = () => {
const data = React.useState(0);
console.log(data);
return (
<div>
<h3>Total click: 0</h3>
<button>Click me</button>
</div>
);
};
ReactDOM.render(<Container />, root);
</script>
</html>
data를 Container 함수 안에서 React.useState()로 선언한다.
🚨 함수는 중괄호로 묶고 리턴을 해줘야 함에 주의하자.
console.log로 data를 출력해보면 [0, f]와 같은 형태로 출력된다.
이는 초기값과 값을 변화시킬 수 있는 함수를 나타내는 것이다.
즉, 처음 data를 선언할 때, React.useState(0)과 같이 0이라는 초기값을 주었기 때문에 [0, f]와 같이 출력된다.
만약 초기값이 없을 경우 undefined로 선언된다.
const root = document.getElementById("root");
function Container() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
return (
<div>
<h3>Total click: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
}
ReactDOM.render(<Container />, root);
위에서 사용했던 코드에서 data를 counter로 바꿔주고
counter를 변화시킬 수 있는 setCounter 함수를 React.useState 함수에 선언해준다.
그리고 버튼을 클릭하면 실행되는 onClick 함수를 선언한다.
onClick 함수는 counter의 값을 변화시킬 수 있는 setCounter 함수를 호출한다.
setCounter 함수는 counter를 1 증가시키고 화면을 리렌더링한다.
🚨 주의!
setCounter 함수 안에서 1을 증가시키기 위해 counter++를 사용하면 안된다.
이유는 전위 연산자, 후위 연산자의 차이에서 나타난다.
전위 연산자는 ++counter, 후위 연산자는 counter++로 사용하는데
후위 연산자의 경우 할당 후 counter를 증가시킨다.
그렇기 때문에 렌더링 과정에서 할당이 되고 난 뒤 counter가 증가해 원하는 결과를 얻을 수 없다.
만약 사용하려면 ++counter와 같은 전위 연산자를 사용하도록 하자.
✅ State를 세팅하는 방법
1. 직접 값을 설정
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1); // (a)
// setCounter(987); // (b)
// setCounter("lalalal"); // (c)
};
(a) counter라는 변수에 1을 더해서 직접 값을 설정하는 방법
(b) 987이라는 값을 설정하는 방법
(c) 숫자가 아닌 문자열로 바꿔서 설정하는 방법
2. 함수 전달
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
};
함수를 통해서 state를 설정
current라는 인자에 1을 더해서 반환(return)하면 언제나 현재 state를 얻어서 변화를 줄 수 있음
🚨 함수 전달을 사용해야 하는 이유
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
setCounter(counter + 1);
setCounter(counter + 1);
};
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
setCounter((current) => current + 1);
setCounter((current) => current + 1);
};
두가지의 경우를 출력해서 사용해보면 이해가 쉽다.
✏️ 첫 번째의 경우
counter에 1을 증가시켜 counter를 설정하는 방식이다.
counter가 0으로 설정되어 있고 버튼을 클릭하여 onClick 함수를 실행시켰다면
첫 번째 setCounter 함수에서 counter인 0에 1을 더하여 counter에 할당한다.
두 번째, 세 번째 setCounter 함수도 마찬가지로 실행 당시의 counter 값인 0에 1을 더해 counter에 할당한다.
결국 counter는 마지막에 할당한 1이 되고 함수가 종료된다.
✏️ 두 번째의 경우
current라는 인자에 1을 더해 반환하는데 항상 현재의 값을 찾아 1을 더한다.
즉, 첫 번째 setCounter 함수에서 현재 counter 값인 0에 1을 더해 1을 할당하고
두 번째 setCounter 함수에서 현재 counter 값인 1에 1을 더해 2가 할당된다.
마지막으로 2에 1을 더해 3으로 할당해 함수가 종료된다.
✏️ 정리
단순 counter + 1과 같은 형태로 사용한다면 함수를 몇 번 호출하더라도 마지막에 할당된 값이 counter에 영향을 준다.
하지만 현재의 값을 가져와 함수 형태로 리턴해준다면 모든 함수가 변수에 영향을 줄 수 있다.
'이론 (Front-end) > React' 카테고리의 다른 글
[React] select 태그를 통한 컴포넌트 제어 (0) | 2023.07.12 |
---|---|
[React] input 값 사용하기 (0) | 2023.06.14 |
[React] JSX와 HTML 속성 차이 (0) | 2023.06.01 |
[React] React 사용해보기 (0) | 2023.04.25 |
[React] React.js를 배우는 이유(Vue.js와 비교) (0) | 2023.04.18 |