setState의 스코프 안에서 해당 state를 다룰 때는 조심해야 한다....
왜냐하면........
1) state
가 바뀌면 화면 전체가 자동으로 다시 그려진다. (리렌더링)
참고로 let
은 값이 바뀌어도 다시 렌더링 하지 않는다.
2) setState
는 비동기로 작동한다. = state
의 값은 setState
가 호출되는 시점이 아닌, 해당 코드가 들어있는 함수가 모두 실행된 이후에 바뀐다.
💡 Why?
setState
가 비동기가 아닌 동기로 작동하게 되면 변경될 때마다 바로바로 렌더링이 일어나서 비효율적이기 때문이다.
함수 안에 setState
가 여러개 있으면
함수 하나를 실행시키는데 렌더링을 여러번 하게 되어서 성능상 좋지 않다.
따라서 임시 저장소에 모아두었다가 코드를 끝까지 읽고 한번에 바꿔서 렌더링 한다.
👆🏻 if문 위에 setMyWriter가 있어도, if문에서는 아직 writer에 값이 들어가있지 않은 상태이다. 그래서 isActive가 true로 바뀌지 않는다.
BoardWrite.Container에서는
즉각적으로 값을 읽어서 if문을 돌리기 위해서 event.target.value
를 사용했다.
이해가 잘 안돼서 돌려본 코드!
import { useState } from "react";
export default function stateTest() {
const [value1, setValue1] = useState(0);
const onClick1 = () => {
setValue1(value1 + 1); // 지금 value1은 0
setValue1(value1 + 1); // 여기도 value1은 0
setValue1(value1 + 1); // 여기도!!! value1은 0
console.log("value1: " + value1);
console.log("value1: " + value1);
console.log("value1: " + value1);
};
return (
<div className="App">
<button onClick={onClick1}>+</button>
<h1>value1 : {value1}</h1>
<h1>value1 : {value1}</h1>
<h1>value1 : {value1}</h1>
</div>
);
}
setValue1(value1 + 1)
을 세번 하더라도, 이 함수 안에서 가지고 있는 value1의 값은 항상 0이기 때문에 첫번째 setValue1에서도, 두번째 세번째에서도 결과는 1이 된다.
onClick1이 한번 더 실행되면 이제 함수가 한번 끝났으므로, setValue1(value1 + 1)
이 한번 실행되어서 value1에는 1이 들어가있고, 이 함수가 종료되면 value1에 1을 더한 2가 들어가게 된다.
const onClickCount = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};
위 함수가 실행되면 count를 증가시키는 setCount가 4개나 있음에도 불구하고 count의 값은 1만 증가된다.
변경된 값이 바로 반영되는 것이 아니고 임시 저장공간에 넣어두고, 함수가 끝나고 나서 값이 변경되기 때문이다ㅜㅜ
이럴 때 prev
를 사용하면 임시 저장공간에 있는 값을 가져올 수 있다!!
임시 저장공간에 값이 없으면 default 값을 가져온다.
(prev) 대신 (prevState)로 써도 된다.
리렌더는 동일하게 함수가 종료되고 나서 한번만 일어난다.
const [count, setCount] = useState(0);
const onClickCount = () => {
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
};
const [isOpen, setIsOpen] = useState(false);
const onToggleModal = () => {
setIsOpen((prev) => !prev);
};