티스토리 뷰

state 변경 시 useState를 쓰는 이유

정확히 말하면 변수를 쓰지않고 useState로 관리하는 이유

함수형 컴포넌트에서 화면에 보여주는 상태가 변할때마다 적절히 재렌더링 하기 위해서입니다.

만약 재렌더링이 필요없이 잠깐만 사용하는 데이터라면 그냥 변수를 사용해도 됩니다.

 

useState훅을 사용하면 state, setState 가 반환되고 이것을 보통 비구조화 할당을 통해 받아서 사용합니다.

setState함수를 통해 state를 변경하면 function 컴포넌트가 다시 실행되고() virtual DOM을 리턴합니다.

그리고 리턴한 virtual DOM과 비교해서 state가 달라졌다면

달라진 부분에 해당하는 값을 업데이트 합니다.

 

 

1.이쯤에서 두가지가 궁금해집니다. 대체 setState는 어떻게 재렌더링을 trigger하는가?

2.함수가 재실행되는데 어떻게 state가 다시 초기값으로 바뀌지 않고 계속 살아있는가?

 

1번은 아직 이해하지 못했습니다. 나중에 다시 포스팅하겠습니다.

2번.

이전 상태와 지금 상태의 변경이 있는지를 감지하기 위해서는 이전상태에 대한 정보를 가지고 있어야하는데,

useState는 이 문제를 클로저를 통해 해결합니다. 함수 외부(전역)에 state를 선언하고 함수를 같은 레벨에서 선언하기 때문에

함수가 state에 클로저로 접근이 가능하고

함수가 재실행되도 초기화되지않고 이전의 value를 가지고 있는 것 같습니다.

 

 

state를 바로 변경하면 안되고 setState를 쓰는 이유

그전에 불변성이란게 무엇이고 대체 왜 불변성을 지켜야 하는지 이해해야 합니다.

불변성이란 메모리 영역에서 데이터의 직접적인 변경을 하지 않는 것을 뜻합니다.

그럼 그 불변성을 왜 지켜야 할까요?

왜 불변성을 지키지 않으면 렌더링이 안되는 걸까요?

const userState = {
  name: "kiwon",
  age: 19,
  hobby: ["등산", "독서"],
  skills: {
    frontend: ["javascript", "React", "Redux"],
    backend: ["java", "python", "nodejs"],
    other: ["aws", "github"],
  },
  location: "인천",
};

불변성을 지키지 않고 이 State를 변경시켜보겠습니다.

userState.hobby[0] = "헬스";

그럼 아마 userState가 이렇게 바뀔겁니다.

const userState = {
  name: "kiwon",
  age: 19,
  hobby: ["헬스", "독서"],
  skills: {
    frontend: ["javascript", "React", "Redux"],
    backend: ["java", "python", "nodejs"],
    other: ["aws", "github"],
  },
  location: "인천",
};

이렇게 State의 value가 직접 바뀌었을때 Update를 감지해서 리랜더링을 시키려면

데이터가 변했는지 하나하나 비교해야 하니 아주 비효율적이겠죠?

그래서 리액트에서는 데이터를 비교할때 얕은 비교를 해서 성능을 최적화합니다.

 

얕은 비교

객체의 참조값만 비교하여 상태변화를 감지하는 것을 말합니다. 이는 객체의 프로퍼티를 하나하나 비교하지 않고 참조 주소값만 비교하기 때문에 계산 리소스를 줄여주어 리액트에서 효율적으로 상태 업데이트를 할 수 있습니다. 

즉, 객체의 주소가 변경되지 않고 내부의 값만 바뀌면 바뀐것으로 인식을 안합니다.

 

그래서 setState로 값을 변경할때 spread operator, map, filter, slice, reduce 등의 메소드를 사용합니다.

원시타입일 경우에는 setState에 값을 바로 넣어도 되지만 참조타입인 경우에는 새로운 객체를 생성해서 넣어줘야

얕은 비교가 가능하기 때문입니다.

예를들어 slice와 달리 splice같은 메서드는 원본배열을 수정합니다.

그래서 새로운 객체를 리턴하는 slice나 map같은 메서드를 잘 써야합니다.

우리는 새로운 객체가 필요하니까요.

// 원시타입
const [number, setNumber] = useState(0)
setState(3)

// 참조타입
const [person, setPerson] = useState({ name: '', age: 30 })
setState({...person, name: 'byun'})

*원시타입의 데이터는 그 자체로 불변성이 유지됩니다. 

 

이 외에도 불변성을 유지함으로써 사이드 이펙트를 방지할 수 있습니다.

함부로 원본의 값을 변경했다가는 어디서 쓰이고 있는지 모르는 다른 객체에서 예상치 못한 에러가 발생할 수 있기 때문입니다.

즉 불변성을 지켜주지 않으면 오히려 프로그래밍의 복잡도가 올라갈 수 있습니다.

 

얕은 복사, 깊은 복사 에 대해 공부한 글입니다.

https://pungwa.tistory.com/121

 

얕은 복사, 깊은 복사

얕은 복사에 대해 세 번 정도 글을 남긴다. 리덕스의 불변성이 궁금할 때, useState가 어떻게 상태를 변화시키는지 궁금할 때, 그리고 오늘 얕은 복사에 대해 대충 알고 넘어갔다가 결국 면접 자리

pungwa.tistory.com

 

 

 

 

참고

https://yeoulcoding.me/m/149

 

[React] 클로저와 useState Hooks

Overview React Hooks는 React Functional Component(함수형 컴포넌트)에서 상태관리 및 컴포넌트 생명주기 API(Lifecycle API) 등 클래스 컴포넌트에서만 지원했던 기능들을 사용할 수 있도록 도와줍니다. 함수..

yeoulcoding.me

https://poiemaweb.com/js-closure

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2025/05   »
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
글 보관함