Intro
- 버튼을 몇 번 클릭했는지 세는 어플
- React.js의 state
- 컴포넌트에 state 추가
- state 변경 시 UI 리렌더링
state란?
기본으로 데이터가 저장되는 곳.
이 어플에서는 버튼을 몇 번 클릭했는지 세는 counter. 즉 바뀌는 데이터를 state로 만들 수 있다.
컴포넌트나 JSX에 변수(데이터)를 추가하고 싶을 때
바닐라 JS => ${변수}로 전달
span.innerText = `Total clicks: ${counter}`;
React JS => 단순히 중괄호에 변수를 넣어준다.
<h3>Total clicks: {counter}</h3>
데이터가 변경되어, 사용자에게 변화된 내용을 보여주고 싶을 때 (리렌더링)
1. render 함수를 다시 호출해 UI 업데이트
데이터가 변경될 시, render 함수를 호출해 화면을 새롭게 업데이트 하는 방법이다.
이 어플에서 render 함수가 호출되는 2가지 상황과 counter의 변화를 비교하면 다음과 같다.
- 어플리케이션이 처음 실행될 때 -> render 함수 호출
-> 최초 실행 시 Container 컴포넌트를 root div에 담아준다.
-> Container함수 호출돼서 React element 반환
-> counter 0 - 버튼의 클릭 시 등록한 이벤트 리스너인 countUp() 호출
-> counter 증가 -> render 함수 호출 ( 사용자에게 바뀐 데이터를 보여주기 위해서 리렌더링함)
-> 최초 실행 시 Container 컴포넌트를 root div에 담아준다.
-> Container함수 호출돼서 React element 반환(이때, Container 컴포넌트가 바뀐 counter값을 가지고 업데이트)
-> counter 1 (업데이트된 값)
여기서 눈여겨볼 점은 버튼 클릭 시 Container 컴포넌트 전체를 리렌더링하는거지만 실제론 HTML 태그 안에서는 변화되는 숫자(counter)만 바뀌고 있다는 것이다. ( 새 컴포넌트를 생성하거나, 전체를 다시 만들지 않고 )
<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 clicks: {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
render();
</script>
하지만 위 방식은 데이터가 바뀔 때마다 render 함수를 반복적으로 호출해줘야 한다는 단점이 있다.
2. useState 함수를 이용해 리렌더링
userState함수는 React.js 어플 내에서 데이터를 보관하고 자동으로 리렌더링을 일으킬 수 있는 방법이다.
useState 함수는 배열 하나를 주는데, 배열의 첫 번째 요소는 우리가 담으려는 data값이고, 두 번째 요소는 이 data값을 바꿀 때 사용하는 modifier이다. 우리는 배열의 데이터를 [0], [1] 같은 형식으로 값을 가져오지 않고 데이터에 counter나 modifier 같은 이름을 붙여 사용하도록 한다.
const data = React.userState(); // [undefined, f]
const [counter, modifier] = React.useState(0); // 초기값 0 할당 [0, f]
// 즉 위의 코드 한줄이 아래 4~7 코드를 대신하고있다는 걸 알 수있음.
let counter = 0;
function countUp(){
//code
}
아무튼, React.useState 함수는 counter 같은 데이터를 숫자형 데이터로 건네주고, 그 데이터 값을 바꿀 함수(modifier, 밑에서는 setCounter)도 함께 준다. modifier 함수를 가지고 state를 변경할 때 컴포넌트가 재생성된다. 즉, 데이터(state)가 바뀔 때마다 컴포넌트를 리렌더링하고 UI를 refresh한다. 물론, 전체 화면이 리렌더링이 되는것이 아니고 오직 modified 컴포넌트(counter)만 리렌더링된다.
state를 세팅해주는 2가지 방법 (setState)
- setCounter(5) => 직접 값을 설정하는 것
- 현재 state를 바탕으로 다음 state를 계산하는 방법
- setCounter(counter+1) => 직접 값을 설정해주기
- setCounter((current) => current + 1) ; => 함수 전달하기 ( 더 안전한 방법 )
(첫번째 인자 : 현재값, 함수의 return 값 : 새로운 state)
state를 세팅하기 위해서 setCounter() 함수를 사용했다. setCounter() 함수에는 직접 값을 설정하거나 함수를 전달해 줄 수 있는데, 함수는 언제나 현재 state를 얻도록 해준다. 따라서 예상치 못한 업데이트가 다른곳에서 일어났다고 해도, 그게 혼동을 주는걸 방지하기 때문에 더 안전하다.
<script type="text/babel">
const root = document.getElementById("root");
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
//setCounter(counter + 1);
setCounter((current) => current + 1);
}
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
※추가 참고. jsx에서는 속성으로 class나 for을 사용할 수 없다. 그 대신 className과 htmlFor이라고 쓴다.
'WEB > React' 카테고리의 다른 글
[React] API 사용하기 (0) | 2022.02.02 |
---|---|
[React] 배열 State (0) | 2022.02.02 |
[React] Effects (useEffect, clean-up) (0) | 2022.01.29 |
[React] Props (Memo, Props Types) (0) | 2022.01.28 |
[React] Component, JSX (0) | 2022.01.26 |