티스토리 뷰
참고 : https://stackoverflow.com/questions/58860021/why-react-hook-usestate-uses-const-and-not-let
<!DOCTYPE html>
<html lang="en">
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/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 [counter, setCounter] = React.useState(0);
const onClick = () => {
// setCounter(counter + 1);
setCounter((cur) => cur + 1);
};
return (
<div>
<h3>Total clicks: {counter}</h3>
<button onClick={onClick}>Click me</button>
</div>
);
};
ReactDOM.render(<Container />, root);
</script>
</html>
간단하게 위와 같은 코드가 있다.
React + JSX를 사용해서 구현한 코드이며, 컴파일은 바벨을 이용해서 로컬에서 수행한다.
궁금한건 Container라는 함수가 수행될 때, useState가 있음에도 최초에 한 번만 수행되고 그 다음엔 수행되지 않는 이유이다.
먼저 참고에 링크를 걸어둔 곳에서 제공한 샘플 코드를 보자.
<!DOCTYPE html>
<html lang="en">
<body>
<div id="root"></div>
</body>
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// https://stackoverflow.com/questions/58860021/why-react-hook-usestate-uses-const-and-not-let
let _state;
let _initialized = false;
function useState(initialValue) {
if (!_initialized) {
_state = initialValue;
_initialized = true;
}
return [_state, (v) => (_state = v)];
}
function Component() {
const [count, setCount] = useState(0);
setCount(count + 1);
}
Component();
Component();
</script>
</html>
먼저 말해둘건 링크에도 명시되어 있지만 절대 useState 함수가 위와 같이 간단하진 않다.
계속 살펴보면, _initialized 변수를 통해 상태를 관리하는 것을 볼 수 있다. 또한 destructuring을 통해 setCount 함수에 Arrow function을 할당하고 있다.
그렇기에 상단에 useState가 계속 실행되더라도, 처음 실행된게 아니라는걸 알고 있어 두 번째부터는 전달 받은 값으로 _state를 수정해준다.
또한, 베스트 프렉티스(?)를 통해 아래와 같이 사용하도록 하는걸 본 적 있을 것이다.
// setCounter(counter + 1);
setCounter((cur) => cur + 1);
간단하게 얘기하면 counter를 그대로 넘겨주면 Race Condition 문제가 발생할 수 있으므로 아래와 같이 전달해주게 된다.
근데 이렇게 되면 위에 있는 useState 함수 예시랑 좀 안맞는다는 생각이 들 것이다. 그래서 React에서는 내부적으로 stateType에 따라 리턴을 바꿔서 해주게 된다. 아래 코드는 공식 코드이다.
function stateType(state, action) {
return typeof action === "function" ? action(state) : action;
}
위와 같이 setCount 함수의 인자로 함수를 전달하면 stateType 함수에서 적절히 변환해서 전달해주게 된다. 대략 예시를 들면,
let _state;
let _initialized = false;
function useState(initialValue) {
if (!_initialized) {
_state = initialValue;
_initialized = true;
}
return [_state, (v) => stateType(_state, v)];
}
function stateType(state, action) {
return typeof action === "function" ? action(state) : action;
}
function Component() {
const [count, setCount] = useState(0);
// setCount(count + 1);
setCount((cur) => cur + 1);
}
Component();
Component();
위와 같은 모양이 되지 않을까 싶다.
'Web > FrontEnd' 카테고리의 다른 글
react-router-dom v6 generic 미지원 (1) | 2022.01.27 |
---|---|
[JS] 문자를 숫자로 간단하게 바꾸기 (0) | 2021.12.19 |
- Total
- Today
- Yesterday
- terraform
- teplate
- cloudsecurity
- .get()
- web
- temlate
- IAM
- stateType
- ControlTower
- aws
- platform
- ViaAWSService
- 2xx
- steampipe
- security
- scp
- CIS
- defaulttheme
- Cloud
- compliance
- fleet manager
- conftest policy
- opensource
- 우주와컴퓨터
- findinglatestversion
- AWS #CIS
- 4xx
- JavaScript
- REACT
- 계정정보저장
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |