React | state, useState, setState
keyword
state, useState(), setState(), re-rendering
요약
useState
, setState
사용 장점
데이터(값)를 업데이트시키고 메인 컴포넌트를 리렌더링함
즉, state가 바뀌면 리렌더링을 자동으로 발생시킴.
state 상태변경값 변수선언 -> Event Listen -> Event Update -> UI display
state
state
기본적으로 데이터가 저장되는 곳
state, event listening, update, re-rendering
어떻게 하면 React.js 어플리케이션에서 바뀌는 데이터값을 담아줄 수 있을까?
(1) 가변하는 데이터 저장 변수 + (2) 이벤트 리스닝 (3) 이벤트 업데이트 + (3) 새로고침(리렌더링) 방법
- (bad way) 일반 변수선언 + 실행 함수 + 리렌더링 함수 = 수작업 업데이트
- (best way) useState 변수 선언 + 실행 함수 = 자동 업데이트
- (bad way) 일반 변수선언 + 실행 함수 + 리렌더링 함수 = 수작업 업데이트
변수를 JSX함수에 전달하는 방법? {변수명}
예제
카운트업 함수 만들기
<!DOCTYPE html>
<html lang="en">
<head> </head>
<body>
<div id="root"></div>
</body>
<!-- react.js-->
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.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);
}
function Container() {
return (
<div>
<h3>Total Click: {counter}</h3>
<button onClick={countUp}>Click me</button>
</div>
);
}
//ReactDOM.render(<Container />, root);
render();
</script>
</html>
단점
: 데이터가 바뀔 때마다, 계속해서 리렌더링 함수 render();
를 호출 해줘야함.
이유
: 위 컴포넌트는 단 한번만 렌더링하고 끝이고, UI를 새로고침해주는 코드가 없기 때문에, 새로 리렌더링 함수를 다른 함수 실행시 매번 같이 실행해줘야 함.
리액트
VS바닐라자바스크립트
업데이트 차이
자바스크립트
는 카운터가 업데이트 될 때, 해당 태그 전체가 업데이트 됨.
<span>
태그 전체
<span>Total Clicks: 1</span>
이 업데이트 됨
리액트
는 UI에서 바뀐 부분만 업데이트 함.
- 오직
{counter}
부분만 업데이트 함. <h3>
"Total Click:"
등 다른 태그들을 재생성할 필요도 없음.
리액트.js
업데이트 방식
- 이전에 렌더링된 컴포넌트 확인
- 다음에 렌더링될 컴포넌트 확인
- 오로지 바뀐 부분만 찾아서 업데이트 리렌더링 해줌
리액트 장점
- 굉장히 인터렉티브한 어플리케이션을 만들 수 있음.
- 여러가지 요소들을 리렌더링하려고 해도 전부 다 새로 생성하지 않음
- (best way) useState 변수 선언 + 실행함수 = 자동 업데이트
기존 방법
let counter = 0; 변수에 담기
새로운 방법
let counter = useState(초기값);
👉 콘솔창에 Array배열을 받게됨.
👉 [undefined, f함수] 배열은
[(현재)데이터, 데이터를 바꿀때 사용하는 함수]를 의미.
(=> 위 두 요소들이, 우리가 이전 예제의 counte변수와 countUp()함수의 역할을 대신해주고 있음.)
useState() 방법 예제
function App() {
const data = React.useState();
console.log(data);
return (
<div>
<h3>Total Click: {counter}</h3>
<button>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
React.useState() 함수는 초기값을 설정 가능.
const data = React.useState(0);
만약에 데이터값을 사용하고 싶다면? data[0], data[1] 이렇게 접근 가능.
const data = React.useState(999);
const counter = data[0];
const modifier = data[1];
❗더 좋은 방법
구조분해할당으로 처리
let counter = React.useState(초기값);
=> let [currentValue, modifier] = React.useSatet(초기값)
<script type="text/babel">
const root = document.getElementById("root");
function App() {
const [counter, modifier] = React.useState(0);
return (
<div>
<h3>Total Click: {counter}</h3>
<button>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
- 업데이트 함수 만들기
❗ counter 변수값 업데이트 되야하니까const -> let
으로 변경
let [counter, modifier] = React.useState(0);
const onClick = () => {
counter = counter + 1;
console.log(counter);
};
- 이벤트리스너 함수 등록
<button onClick={onClick}>Click me</button>
- 화면을 리렌더링
- 업데이트 함수로 리렌더링을 자동으로 발생시킴.
- 업데이트 함수명은 주로 set+함수명으로 설정함.
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
최종 코드
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</body>
</html>
❗setState() 사용법
setState() 함수를 셋팅하는 2가지 방법
- 1) 직접할당: setState(현재값+1)
- 2) 함수할당: setState((현재값) => {업데이트 리턴값 & 함수}) 함수
- (함수의 첫번째 인자는 현재 state 임)
1) 직접할당: setState(현재값+1)
setState(state+1)
const [counter, setCounter] = React.useState();
const onClick = () => {
setCounter(counter+1);
};
- 현재 state랑 state업데이트에 관련이 없는 값을 새로운 state로 하고싶은 경우
2) 함수할당: setState((현재값) => {리턴값&규칙}) 함수
setState((state) => (state+1))
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
};
- 현재 state값에 변화를 주어서 새로운 state로 업데이트를 하고 경우
- 이 함수의 1번째 argument는 현재값이고, 리턴값이 새로운 state가 됨
결론
: 2번 함수할당 방식이 현재값 업데이트에는 더 좋음
이유
:
- 현재값을 바탕으로 새로운 값을 계산해 업데이트해주는 2번 방식이 더 안전한 방식이라고 함
- {함수} 사용으로 current가 확실히 현재값이라는 것을 보장해줌
- (2)함수할당 방식은 함수내에서 호출 횟수마다 current상태값을 업데이트해주는 것을 보장함.
- (1)직접할당 방식은 함수내에서 호출 횟수에 상관없이 무조건 1번만 업데이트 해줌.
전체코드
<!DOCTYPE html>
<html>
<body>
<div id="root"></div>
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/[email protected]/babel.min.js"></script>
<script type="text/babel">
const root = document.getElementById("root");
function App() {
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter((current) => current + 1);
};
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
}
ReactDOM.render(<App />, root);
</script>
</body>
</html>
보충 설명 (setState())
1.직접할당 2.함수할당 결과값 차이
예제
아래와 같이 코드를 넣고 실행해보면,
- 1번 직접할당: 클릭당 리턴값 : 1,2,3,4,5
- 2번 함수할당: 클릭당 리턴값 : 5,10,15,20
1번 직접할당: 값으로 여러번 호출한 결과값: 1,2,3,4,5
function onClick() {
setCounter(counter + 1);
setCounter(counter + 1);
setCounter(counter + 1);
setCounter(counter + 1);
setCounter(counter + 1);
}
2번 함수할당: 함수로 여러번 호출한 결과값 5,10,15,20
function onClick() {
setCounter(current => current+ 1);
setCounter(current => current+ 1);
setCounter(current => current+ 1);
setCounter(current => current+ 1);
setCounter(current => current+ 1);
}
결과
- 1번으로 돌렸을 경우, setCounter를 몇 번을 호출해도 한 번만 실행됨. (counter가 1만 증가)
- 2번으로 돌렸을 경우, setCounter가 호출된 횟수 만큼 counter가 5씩 증가됨.
<참고>
https://nomadcoders.co/react-for-beginners
https://ko.reactjs.org/tutorial/tutorial.html
<더 읽어보기>
SyntheticEvent, Event Pooling, event.persist():
https://ko.reactjs.org/docs/events.html
https://ko.reactjs.org/docs/handling-events.html
https://medium.com/react-native-seoul/react-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%A5%BC-%EC%B2%98%EC%9D%8C%EB%B6%80%ED%84%B0-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90-06-%ED%95%A9%EC%84%B1-%EC%9D%B4%EB%B2%A4%ED%8A%B8%EC%99%80-event-pooling-6b4a0801c9b9
https://abangpa1ace.tistory.com/129
https://frontcode.tistory.com/60
Author And Source
이 문제에 관하여(React | state, useState, setState), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sujeongji/state저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)