늘 겸손하게

React - 직접 state를 변경하지 않고 setState를 호출하는 이유 본문

Programming/React

React - 직접 state를 변경하지 않고 setState를 호출하는 이유

besforyou999 2022. 7. 26. 23:34

state를 this.state으로 직접 변경할 수 있습니다. 하지만 공식문서도 그렇고 많은 글을 보면 절대로 직접 수정하지 말고 setState로 state를 변경하라고 합니다. 하지만 왜 그래야할까요?

 

[ state를 직접 변경하면 안되는 이유 ]

 

React는 Unidirectional data flow를 따릅니다. 이 말의 의미는 React 내부의 데이터 플로우는 언제나 단방향, 원형으로 순환할것으로 예측한다는 의미입니다. React를 이렇게 실행되게 하기 위해 개발자들은 React를 함수형 프로그래밍과 비슷하게 만들었습니다.

 

함수형 프로그래밍에서 가장 중요한 규칙은 immutability(불변성)입니다.

 

 

[ React의 Unidirectional data flow가 동작하는 방식 ]

 

  • state는 컴포넌트의 데이터를 저장중인 데이터 저장소
  • 컴포넌트의 view는 state를 기반으로 렌더링 됨
  • view에 변경사항이 필요하면 state값 변경 필요
  • 이를 위해 React는 setState 메소드를 제공. setState는 새로운 state 데이터를 담은 객체를 입력받아 이전 state 객체와 비교하고 병합한 뒤 state 저장소에 새로운 state를 추가함
  • state 저장소의 데이터가 변경되면 react는 변경된 데이터로 리렌더링을 시작

 

이전 state와 현재 state를 비교 => shallow compare (얕은 비교)

 

위 과정은 컴포넌트가 제거되기 전까지 반복됨

 

React Data flow without flux

 

 

만약 state를 직접 수정하면 이전 state값무결성을 오염시켜 이전 state와 현재 state의 shallow compare와 병합을 방해하여 React의 모든 생명 주기 메소드를 방해합니다. 결과적으로 앱이 비정상적으로 작동하거나 죽어버립니다(crash).

 

 

[ React에서 state를 다룰때 흔히 하는 실수 ]

 

this.state = {
    a: [1, 2, 3, 4]
}

// 리액트의 state를 변경해야함
// 배열에 5를 추가

// 나쁜 예
const b = this.state.a.push(5)
this.setState({
    a: b
})

 

 

위 예시코드는 state를 직접 변경하고 있습니다. 변수 b에 배열 a에 원소 5를 추가한 새로운 배열을 할당한것같지만 내부적으로 변수 b는 배열 a를 참조하고 있을뿐 새로운 배열을 할당받은것이 아닙니다. 위 코드는 아래 코드와 같은 일을 한셈입니다

 

 

this.state.a.push(6)
this.setState({})

 

 

그렇다면 올바른 state 수정 방식은 어떤 방식일까요? 존재하는 state의 일부를 변경하고 싶다면 원본 state의 복사본이 먼저 필요합니다. 그 후, 복사본에 수정을 가하고 setState를 호출해야합니다.

 

 

// 오리지널 state
this.state = {
	a: [1, 2, 3, 4]
}

// 복사본 생성
const currentStateCopy = [...this.state.a]

// 복사본 수정
currentStateCopy.push(5)

// setState 호출
this.setState({
	a: currentStateCopy
})

 

이러한 방식으로 이전 state값이 오염시키지 않고 새로운 state값을 제공해야합니다

 

[ 요약 ]

 

this.state로 state값을 직접 변경하면 state의 무결성을 오염시켜 이전 state와 새로운 state의 차이점을 비교하는 shallow compare를 방해하여 React 데이터 플로우인 Unidirectional data flow를 망가뜨려 앱이 예측 불가능해지고 심한 경우 crash될 수 있다

 

 

 

[ 출처 ]

https://ko.reactjs.org/docs/faq-state.html

https://stackoverflow.com/questions/37755997/why-cant-i-directly-modify-a-components-state-really

'Programming > React' 카테고리의 다른 글

React - 리액트 메모이제이션  (0) 2022.07.28
React - React.memo, useCallback, useMemo  (0) 2022.07.28
React - JSX  (0) 2022.07.26
React - 생명 주기 메소드  (0) 2022.07.26
React - Pure component  (0) 2022.07.23