profile image

L o a d i n g . . .

article thumbnail image
Published 2024. 7. 24. 12:39

State

리액트 컴포넌트의 상태를 의미함, 즉 리액트 컴포넌트의 변경 가능한 데이터

state는 자바스크립트 객체

state는 사전에 미리 정해진 것이 아니므로 컴포넌트를 개발하는 개발자가 직접 정의해서 사용함

렌더링이나 데이터 흐름에 사용되는 값만 state에 포함시켜야 함

  • 왜냐하면 state가 변경될 경우 컴포넌트가 다시 렌더링 되기 때문에 렌더링과 데이터 흐름에 관련 없는 값을 포함하면, 컴포넌트가 다시 렌더링 되어 성능을 저하 시킬 수 있기 때문
import React, { useState } from 'react';

const WrongExample = () => {
  const [name, setName] = useState('나마니');
  const [count, setCount] = useState(0);
  const [unusedValue, setUnusedValue] = useState('이 값은 렌더링과 관계없음');

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>{name}</p>
      <p>{count}</p>
      <button onClick={increment}>Increase Count</button>
    </div>
  );
};

export default WrongExample;

`unusedValue`는 `state` 에 포함되어 있지만 렌더링에 영향을 주지 않으므로 결과에 나타나지 않음.


 

결과

처음 결과

<div>
  <p>나마니</p>
  <p>0</p>
  <button>Increase Count</button>
</div>

 

이후 `Increase Count` 버튼을 누르면 `count` 값이 1씩 증가됨 다시 렌더링이 됨

<div>
  <p>나마니</p>
  <p>1</p>
  <button>Increase Count</button>
</div>

해당 값은 컴포넌트의 성능에 부정적인 영향을 줄 수 있으므로 불필요하게 `state` 에 포함시키지 말 것

 


올바른 결과

import React, { useState } from 'react';

const CorrectExample = () => {
  const [name, setName] = useState('나마니');
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>{name}</p>
      <p>{count}</p>
      <button onClick={increment}>Increase Count</button>
    </div>
  );
};

export default CorrectExample;

여기서는 `name`과 `count`만 `state`로 관리하고 있고, 두 값 모두 렌더링에 사용되므로 `state`에 포함시키는 것이 많음

 

만약 컴포넌트에 사용되지 않는 데이터를 관리해야 한다면, 그 값을 단순한 변수로 두는 것이 좋다.
그렇게 하면 불필요한 렌더링을 피할 수 있다.

state의 특징

모든 클래스 컴포넌트에는 `constructor`라는 이름의 함수가 존재한다.

class LikeButton extends React.Component {
	constructor(props) {
		super(props);
		
		this.state = {
			liked: false
		};
	}
}

위 코드에서 `this.state`라는 부분이 나오는데 이 부분이 바로 현재 컴포넌트의 state를 정의하는 부분이다.

클래스 컴포넌트의 경우 `state`를 생성자에서 정의하고, 함수 컴포넌트는 `state`를 `useState()`라는 훅을 사용해서 정의한다.

`state`는 정의된 이후 직접적인 변경이 불가능하다. (`setState()` 함수를 통해 수정해야 함)

 


생명주기

Lifecycle method, 생명주기 함수

https://soldonii.tistory.com/113

 


Mounting (출생)

https://soldonii.tistory.com/113

 

컴포넌트가 생성되는 시점, 이 과정을 `Mount (마운트)` 라고 한다.

이때 컴포넌트의 `constructor(생성자)` 가 실행된다. 생성자에서는 컴포넌트의 state를 정의하게 된다.

또한 컴포넌트가 렌더링되며 이후에 `componentDidMount()` 함수가 호출된다.

Rendering(렌더링): 컴포넌트의 props와 state의 상태에 기초하여 UI를 어떻게 구성할지 컴포넌트에게 요청하는 작업, 쉽게 말해 해당 컴포넌트를 다시 실행한다고 생각하면 된다.
렌더링이 발생하면 선언부에서 초기화 한 값으로 변경되고, 렌더링의 발생 조건은 컴포넌트가 가지고 있는 값이 변경될 때이다. 그래서 `state`를 사용해야하고, 그 외에 다른 것들은 값이 고정되어 있어야 한다.  (리액트의 순수성)
https://react.dev/learn/keeping-components-pure


렌더링이 왜 필요한가?
1. UI 상태 관리의 복잡성 해결: 전통적인 방법으로는 DOM을 직접 조작하면서 모든 변경사항을 관리해야 함
2. 가상 DOM: 가상 DOM은 실제 DOM의 가벼운 복사본으로, 상태 변화가 있을 때마다 새 가상 DOM을 생성하고 이전 가상 DOM과 비교하여 실제 DOM을 최소한으로 업데이트 한다. (참고: https://namaniflow.tistory.com/292)
3. 컴포넌트 기반 아키텍처: 리액트는 UI를 재사용 가능한 컴포넌트로 분리해서 개발할 수 있게 하는데, 각 컴포넌트는 독립적인 상태와 렌더링 로직을 갖고 있다. 때문에 변경이 필요한 부분만 업데이트 되도록 한다.
4. 데이터 흐름과 상태 관리: 리액트는 단방향 데이터 흐름을 지향한다. 즉, 상태가 변경되면 그 상태를 기반으로 컴포넌트를 다시 렌더링하여 UI를 업데이트 한다. state와 UI가 항상 일치하게 유지된다.
5. 성능 최적화: 가상 DOM을 통해 불필요한 DOM 업데이트를 피하고, 최적의 방법으로 UI 업데이트 가능하다.

 


Updating

https://soldonii.tistory.com/113

 

컴포넌트의 props가 변경되거나 setState() 함수 호출에 의해 state가 변경되거나, forceUpdate()라는 강제 업데이트 함수 호출로 인해 컴포넌트가 다시 렌더링 된다.

렌더링 이후에 `componentDidUpdate()` 함수가 호출 된다.


Unmount(언마운트)

https://soldonii.tistory.com/113

상위 컴포넌트에서 현재 컴포넌트를 더 이상 화면에 표시하지 않게 될 때 언마운트 된다.

언마운트 직전에 `componentWillUnmount()` 함수가 호출 된다.


참고

1. https://velog.io/@rookieand/React-%EC%97%90%EC%84%9C-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4%EB%9E%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C - 생명주기 이미지

2. https://velog.io/@rookieand/React-%EC%97%90%EC%84%9C-%EB%A0%8C%EB%8D%94%EB%A7%81%EC%9D%B4%EB%9E%80-%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C - 렌더링이란 무엇일까?

복사했습니다!