리액트를 사용한다면 State라는 것을 정말 많이 사용하게 된다. 하지만 state의 작동원리나 개념을 잘 파악하지 못한 채로 사용하다 보니 에러를 마주해도 해결하기가 어려웠다. state에 대해 좀 더 공부해야할 필요성을 느끼고 정리해봤다.
state 형태
state는 리액트 컴포넌트에서 변수로 활용한다. 세가지 형태로 이루어져 있다.
state : 변수
setState : 변수를 바꾸는 기능
useState : 변수를 만드는 기능
const [state, setState] = useState(); //형태
const [title, setTitle] = useState("제목"); //예시
setTitle("부제목") // setState에 다른 값을 입력하면 state 값이 바뀌게 된다.
state를 사용하는 이유
state의 가장 큰 특징은 리렌더링이다. 이 부분에 관해서는 아래 쪽에서 더 자세하게 설명할 예정이다. 리렌더링이란 간단하게 말하면 화면을 다시 불러와서 보여주는 것이다. state의 변수값이 변경되면 자동으로 DOM을 새롭게 그려준다. 새로고침 하지 않아도. 자바스크립트의 일반 변수는 변수값이 변경되어도 자동으로 리렌더링을 하지 않는다.
state 작동 원리
그럼 리렌더링이 어떻게 작동되는지 알아보자. state 변수를 선언하면 state에 담긴 데이터는 임시저장공간으로 넘어간다.
그리고 함수가 완전히 끝난 후에 임시저장공간의 가장 마지막 값으로 리렌더링이 이루어진다.
예시를 들어보겠다. 아래 코드 value에 0 값을 담고 setValue에 1을 3번 더 해준다. 우선 함수 안의 값은 0을 출력한다. 이는 함수가 종료되지 않고 함수 내에서 출력했기 때문이다. state는 함수가 종료된 후 리렌더링을 실행한다.
또한 함수 밖의 console.log은 1을 3번 더했음에도 3을 출력하지 않고 1을 출력한다. state는 임시저장공간의 가장 마지막 값만 출력되기 때문이다.
export default function Main() {
const [value, setValue] = useState(0);
const onClickButton = () => {
setValue(value + 1);
setValue(value + 1);
setValue(value + 1);
console.log(value); // 3을 출력하지 않고 0을 출력한다
};
console.log(value); // 3을 출력하지 않고 1을 출력한다
}
왜 이럴까요?
그럼 왜 이렇게 작동을 할까? state는 리렌더링을 통해 값을 출력하는데, 만약 함수 내에서 setState 값이 변경 될 때 마다 리렌더링 된다면 성능에 아주 나쁜 영향을 미칠 것이다. 그렇기 때문에 state는 함수 실행이 끝난 후에 모든 값을 배칭(batching)해서 하나의 값으로 리렌더링 한다. 결국 성능 최적화 때문이라는 말이다.
모든 값을 누적해서 출력할 수는 없을까요?
위의 작동원리는 비동기로 작동한다. 이를 동기로 바꿔주면 setState한 모든 값을 적용할 수 있다. 바로 setState 매개변수에 함수를 넣어 주는 것이다. 아래 처럼 함수로 인자를 받아 1을 더해주면 큐에 값이 저장되어 순서대로 실행된다.
const onClickButton = () => {
setValue((prev) => prev + 1);
setValue((prev) => prev + 1);
setValue((prev) => prev + 1);
};
console.log(value); //3이 출력된다
이런 여러가지 특징을 고려해야 useState에 의한 에러를 해결할 수 있다.
'프로그래밍⚡️ > React' 카테고리의 다른 글
React-hook의 종류와 custom hook 사용기 (0) | 2023.02.24 |
---|---|
함수 안에서 어떻게 setState가 두번 작동하지? (micro queue, macro queue) (0) | 2023.02.22 |
container/presentational 패턴 사용 후기 (0) | 2023.01.23 |
React, Import와 Export (0) | 2023.01.15 |
JSX ! 뭔지는 알고 쓰자! (0) | 2023.01.15 |