➡️버튼 클릭 횟수, 사용자가 입력한 텍스트, 서버에서 가져온 데이터 등은 모두 상태이다 !
😮상태에 영향을 주는 것
: 사용자 입력이나 서버의 응답, UI의 변화 등 ..
➕추가로 ...
리액트는 불변성을 기반으로 동작하기에,
기존 객체 수정 ( X )
새로운 객체를 생성해 교체👍 ( O )
-> 이렇게 참조 주소를 비교하는 것은 렌더링 성능에 도움을 준다
((변경된 부분만 업데이트 → 브라우저에 최소한의 성능 비용으로 변경 반영!해주기 때문 ))
React는 UI = f(상태)라는 개념을 기반으로 동작해서
즉, 상태가 변경되면 UI가 다시 렌더링된다.
비일관성: UI와 내부 데이터가 일치하지 않는 😮 상황 발생
복잡성 증가: 상태를 효율적으로 관리하지 않으면 코드가 복잡해짐 😢
디버깅 어려움: 상태 변경 흐름을 이해하기 어려워짐
.
.
나의 경우에는 비일관성 문제를 겪어서 렌더링이 바로 되지 않는 문제가 생겼었다
하지만 !!!
상태 관리를 신경쓰기만 해도 UI와 데이터의 일관성을 유지하고,
코드의 가독성과 유지보수성 향상시킬 수 있으며,
디버깅이나 확장도 쉬워질 것이다~
그러니까 알아둬야한다..
우선 개념을 알아보도록 하자
useState는 React에서 컴포넌트의 상태를 선언하고 관리할 수 있도록 도와주는 훅이다.
📌 기본 개념
- 상태 변수 선언
- 상태 변경 함수 제공
앞서 말했듯이 리액트에서는
상태 변경 -> UI 리렌더링이 되기에
쉽게 ~! 동적 UI 를 구현할 수 있다
📌 기본 사용법
const [state, setState] = useState(initialValue);
- state : 현재 상태 값
- setState : 상태를 변경하는 함수
- initialValue : 상태의 초기값 (숫자, 문자열, 배열, 객체 등이 가능함!)
코드를 살펴보며 설명해보면
import React, { useState } from 'react';
function Counter() {
//⭐ 상태 변수 count, 상태 변경 함수 setCount
const [count, setCount] = useState(0);
//⭐➡️ count 초기값 : 0 -> 처음 렌더링때만 적용 !!
//⭐버튼 클릭 시 상태 변경 ➡️ 클릭시 1 증가
const handleIncrement = () => {
setCount(count + 1); //⭐ 상태 변경 예약 & 렌더링 요청, 상태 변경시 리렌더링 ‼️
};
return (
<div>
<p> 현재 카운트: {count} </p>
<button onClick={handleIncrement}>+1 증가</button>
</div>
);
}
export default Counter;
여기서 중요한 건
리액트는 이전 상태와 새로운 상태의 참조를 비교해서 렌더링 여부를 결정한다는 것이다.
.
.
그렇기에
setCount만 설정하면
상태 변경이 예약된 상태이고
위의 코드의 경우 onClick으로 상태가 변경되어야‼️
리렌더링이 이루어진다 🙆♀️
개념을 알았다면
좀 더 본격적으로 ☺️
본격적인 특징과 동작 원리를 공부해보자 ⭐
_
바로 직전에 설명했던 것이다 !~))
React는 성능 최적화를 위해 상태 업데이트를 비동기적으로 처리한다.
setState를 호출한 직후에는 변경된 값이 바로 반영되지 않고 ❌
Batch Processing(일괄 처리)를 통해 여러 상태 변경을 묶어서 처리한다.
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
console.log(count); // 예상: 1 / 실제: 0 (이전 값 출력)
};
이 코드의 문제는 무엇일까 ~?
.
.
정답 : 상태 업데이트를 예약만 하고 바로 실행하지 않기에 문제가 생긴다!
렌더링 시점의 count를 참조하기 때문에 항상 이전 값이 사용되고 있다 😮
어떻게 수정해주면 좋을까 ?
.
.
const handleClick = () => {
setCount(prevCount => prevCount + 1);
console.log(count); // 예상: 1 / 실제: 여전히 이전 값이지만 내부 로직은 올바르게 동작
};
➡️ 이렇게 함수형 업데이트를 활용해서 수정해줄 수 있다 ! 🐱
= 이러면 prevCount를 통해 최신 상태가 유지되고,
다음 렌더링 시에는 올바른 값이 화면에 표시된다. ☺️
React는 불변성 원칙을 따르기 때문에 기존 객체를 직접 수정하면 안된다
➡️
기존 객체를 수정하면
참조 주소가 동일해서 변경이 없다고 판단하여
렌더링이 일어나지 않는다
.
.
- 기존 객체 수정 → 리렌더링 ❌
const [user, setUser] = useState({ name: 'Lee', age: 24 }); const changeName = () => { user.name = 'Kim'; setUser(user); // 참조 주소 동일 → 리렌더링 안 됨 };
- 새로운 객체 → 리렌더링 😉
const changeName = () => { setUser(prevUser => ({ ...prevUser, name: 'Kim' })); };
React에서는 각 상태가 독립적으로 관리된다.
🐱 관련된 상태는 객체 형태로 묶어서 관리 가능하다 → 코드 가독성 올라감 😮
const [user, setUser] = useState({ name: '', age: 0 });
const updateName = (newName) => {
setUser(prevUser => ({ ...prevUser, name: newName }));
};
상태(state)는 React에서 동적 데이터를 관리하고
변경 시 UI가 자동으로 리렌더링 🔃
불변성 유지 중요 ⭐
객체 수정 시 반드시 새로운 객체를 생성해야 리렌더링 작동
setState는 비동기적 ☺️‼️
최신 상태를 보장을 위해서 함수형 업데이트를 사용해야 함
.
.
.
끝 ✌️
오호~~ 공부를 어떻게 해야하는지 점점 감을 잡아가고있네요 기본원리부터 실제로 느꼈던 오류에서 활용된 개념과 느낀 점까지 너무 잘 적었어요 잘하고있습니다 최고!!