[React] React state란? ft. props

정(JJeong)·2022년 10월 9일
0
post-thumbnail

해당 시리즈의 포스트개념 및 이론 정리개인적인 코딩 기록이 혼용되어 포스팅됩니다. 참고 부탁드립니다.



앞서 Todo List를 만들면서 변화된 데이터값을 반영하기 위해 statesetState를 사용하였다.

이것은 정확히 어떤 의미를 갖는지 알아보고 싶었다.


📌 state란?

state는 JS가 가지고 있는 내장 객체이며 컴포넌트 내부에서 변경될 수 있는 데이터값을 다룰 때 주로 사용된다.

이는 props와 흔히 비교가 되는데 둘 모두 렌더링의 결과에 영향을 준다는 공통점이 있다.

그렇다면 둘의 차이는 무엇일까?


state vs props

📢 props

먼저 props를 보자면 이는 컴포넌트에서 사용되는 방식이 마치 함수의 매개변수와 비슷하다.

즉, 매개변수처럼 외부에서 컴포넌트로 전달되는 방식이다.

  • 하위 컴포넌트의 props는 상위 컴포넌트에서 가져오거나 설정한다.

  • 상위 컴포넌트에서 하위 컴포넌트에게 data나 event handler 등을 전달할 때 사용되며, 매개변수와 같이 전달된다.

  • props는 변경 불가능하다.


📢 state

그렇다면 state는 어떨까? state는 컴포넌트의 내부에서 선언(마치 변수와 같다)되고 관리된다.

  • component내부에서 작성되어 관리된다.

  • 가변적인 data를 다룰 때 주로 사용된다.

  • handler 를 통해 state를 update(변경)한다.

  • state는 변경 가능하다.


공통적으로 렌더링되는 결과에 영향을 끼친다는 것은 같지만 성격을 들여다보면 매우 다르다는 것을 알 수 있다.

그럼 위를 보았을 때 state를 변경시킬 수 있는 handler는 무엇일까?



📌 setState

setState는 state 객체에 대한 업데이트를 실행하여 주며 이에 따라 state객체에 담긴 값은 변경될 수 있다.

그리고 이를 통해 state가 변경되면 컴포넌트의 리렌더링이 이뤄진다.


setState는 비동기적으로 이뤄진다.

여기서 우리가 유념해야할 점은 setState는 비동기적이라는 것이다.

우리가 state를 불러올때 보통 this.state와 같이 작성하는데 이 값은 렌더링된 후의 값을 나타낸다.

때문에 비동기적인 setState의 호출 후에 바로 this.state에 변화된 결과가 반영될 것이라고 생각하면 안된다.

만약 기존 state값을 기준으로써 무언가 변경하고자 한다면 함수를 setState에 전달하여 사용해야 한다.

📢 예문

this.state.count의 초기값은 0이라고 가정한다.

🚫 잘못된 실행

incrementCount() {
  this.setState({count: this.state.count + 1});
}

handleSomething() {
  this.incrementCount();	// 예상 변화값 : 0 → 1
  this.incrementCount();	// 예상 변화값 : 1 → 2
  this.incrementCount();	// 예상 변화값 : 2 → 3
}

위처럼 객체로 setState에 전달된 코드의 실행결과를 보면 this.state.count가 예상했던 3이 되는 것이 아니라 1로 나오는 것을 알 수 있다.

그 이유는 React에서 컴포넌트가 갱신되기 전까지는 this.state.count의 값을 계속 0으로 읽기 때문이다.
즉, 리렌더링되어 업데이트 되기 전까진 this.state의 값이 변하지 않고 기존에 렌더링되어 있던 값이 유지된다.

그래서 결국 this.incrementCount()을 아무리 실행한들 매번 0 → 1을 반복할 뿐이기에 결과가 3이 아니라 1이 나오는 것이다.

이를 올바르게 수정하려면 다음과 같이 객체 대신 함수를 전달해야 한다.


✅ 올바른 실행

incrementCount() {
  // 중요: 값을 업데이트할 때 `this.state` 대신 `state` 값을 읽어옵니다.
  this.setState((state) => {
    return {count: state.count + 1}
  });
}

handleSomething() {
  this.incrementCount();
  this.incrementCount();
  this.incrementCount();
}

위처럼 실행하게 되면 리렌더링 전에는 마찬가지로 this.state.count값이 0으로 나오지만 객체로 전달한 것과 달리 리렌더링 후 결과는 3으로 바뀌는 것을 알 수 있다.

이렇게 함수를 전달하게 되면 해당 함수 안에서 이전 state값에 접근할 수 있으며, 최신 state값을 보장한다.

이러한 함수를 updater라고 한다.



이 밖에도 state를 다루는 여러가지 다른 도구들도 존재한다.
그런데 이러한 도구를 따로 쓰는 것이 아니라 하나로 묶어 주는 것이 있는데, 그것이 useState이다.

이는 차후에 알아보도록 하자.




잘못된 부분에 대한 지적은 얼마든지 환영입니다.
감사합니다.

profile
2년차 응애 FE 개발자입니다👶

0개의 댓글