본문 바로가기
Dev/React

[React] State 살펴보기

by 5kdk 2022. 12. 4.

state와 필요한 이유

  • 함수 컴포넌트에서 내부적으로 상태를 관리해야 하는 일이 필요하다. 이를 위해 필요한 것이 state다
  • state는 컴포넌트의 내부에서 변경 가능한 데이터를 다루기 위해 사용하는 객체라고 할 수 있다
  • const, let 등으로 선언한 변수와 다르게 state는 값이 변하면 관련 있는 컴포넌트들이 re-rendering 되어 화면이 바뀐다

 

useState()

import React, { useState } from "react"; // Hook
const [state, setState] = useState(); // [값, 값을 변경할 때 쓰는 함수]

 

  • 일반적으로 리액트에서는 '유동적인 데이터'는 변수에 담아서 사용하지 않고, useState라는 리액트 Hook함수를 사용하여 state라는 저장 공간에 담아 사용한다.
  • useState는 배열을 리턴하는데 배열에는 두 가지 값(값, 값을 변경할 때 쓰는 함수)이 들어있다.
  • 이를 구조 분해 할당하면 state를 함수 컴포넌트 안에서 사용할 수 있게 해 줄 수 있다.
  • 구조 분해 할당 시 관용적으로 [state, setState]와 같이 이름 붙여 사용한다.

 

 

state 불변성

불변성(immutable)은 "변하지 않는 성질"이다. 프로그래밍에서 불변성을 지킨다는 것은, 메모리 영역의 값을 직접적으로 변경하지 않는다는 것을 의미한다.

 

setState() -> 컴포넌트 re-rendering

 

setState는 state는 실행하기 전상태 (이전의 state상태와) 이후 상태를 비교해보고 값이 다르면 re-rendering 하고, 값이 같으면 re-rendering 이 일어나지 않는다. 하지만, 불변성을 지키지 않고 메모리 영역의 값을 직접 변경하면 리액트는 state가 바뀌었다고 인지하지 못한다. 리액트는 이전 state와 이후 state를 비교할 때, 얕은 비교(Shallow Compare)를 하기 때문이다.

카운터 랜더링 화면

 

💡원시 타입 state 다루기

  const [count, setCount] = useState(0);
  const [show, setShow] = useState(true);
  const [operator, setOperator] = useState(operators[0]);

원시 타입(boolean, number, string)은 불변성을 가지고 있다. 변수에 원시 타입의 값을 할당하면, 메모리에 값 자체가 저장된다.

return (
<div>
  <button onClick={() => {
    let result;
    if (operator === "+") result = count + 1;
    if (operator === "-") result = count - 1;
    if (operator === "*") result = count * 1;
    setCount(result);
  }}>
    {operator}1
  </button>
  <button onClick={() => setShow(!show)}>Show and Hide</button>
  <button
    onClick={() => {
      const idx = Math.floor(Math.random() * operator.length);
      setOperator(operators[idx]);
    }}
  >
    Change Operator
  </button>
  <br />
  {show && `Counter: ${count}`}
</div>
);

 

 

💡참조 타입 state 다루기

const [info, setInfo] = useState({
    count: 0,
    show: true,
    operator: operators[0],
});

참조 타입(object)은 메모리 값이 담긴 주소가 저장된다. 아래와 같이 스프레드 연산자를 이용해서 불변성을 가지도록 호출을 해주면, 리액트는 새로운 객체 데이터가 바뀌었다고 인지하게 되고 새롭게 렌더링을 해준다.

return (
<div>
  <button
    onClick={() => {
      let result;
      if (info.operator === "+") result = info.count + 1;
      if (info.operator === "-") result = info.count - 1;
      if (info.operator === "*") result = info.count * 1;
      setInfo({ ...info, count: result });
    }}
  >
    {info.operator}1
  </button>
  <button
    onClick={() => {
      setInfo({ ...info, show: !info.show });
    }}
  >
    Show and Hide
  </button>
  <button
    onClick={() => {
      const idx = Math.floor(Math.random() * operators.length);
      setInfo({ ...info, operator: operators[idx] });
    }}
  >
    Change Operator
  </button>
  <br />
  {info.show && `Counter: ${info.count}`}
</div>
);

 


props와 state비교

props (properties)와 state는 일반 JavaScript 객체이다. 두 객체 모두 렌더링 결과물에 영향을 주는 정보를 갖고 있는데, 한 가지 중요한 방식에서 차이가 있다. props는 (함수 매개변수처럼) 컴포넌트에 전달되는 반면 state는 (함수 내에 선언된 변수처럼) 컴포넌트 안에서 관리된다.

 

댓글