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

디아·2022년 4월 12일
0

리액트 기초

목록 보기
2/5
post-thumbnail

TL;DR
state값을 직접 변경하는 것은 리렌더를 trigger하지 않는다. 즉, 직접 변경한 state 값은 화면에 표시되지 않는다.
setState 함수로 state를 업데이트해야 자동으로 컴포넌트가 리렌더링된다.

Why State?

우선 리액트에서 state를 사용하는 이유부터 알아보자.
예를들어 가계부 리스트의 지출항목을 구현하는데 지출항목의 항목이름(title)을 변경한다고 가정해보자.
아래는 지출항목 컴포넌트이다. 부모 컴포넌트로부터 props로 title을 내려받았다.

function ExpenseItem({title, amount}) {

  return (
    <div>
      <div>
        <h2>항목: {title}</h2>
        <div>금액: ${amount}</div>
      </div>
    </div>
  )
}

export default ExpenseItem;

이 props로 받은 title을 displayTitle 변수에 담고, 버튼 클릭 시 이 변수의 값을 '생수'로 변경하고 변수의 값을 출력하는 이벤트핸들러 함수를 만들어 항목이름을 변경해준다.

function ExpenseItem({title, amount}) {

  let displayTitle = title;
  
  const clickHandler = () => {
    displayTitle = "생수";
    console.log("displayTitle", displayTitle);
  };
  
  return (
    <div>
      <div>
        <h2>항목: {title}</h2>
        <div>금액: ${amount}</div>
      </div>
      <button onClick={clickHandler}>변경</button>
    </div>
  )
}

export default ExpenseItem;

버튼을 클릭해보면 콘솔에는 변경된 값이 잘 출력되지만 화면에는 변경된 값이 표시되지 않는다. 일반 변수의 값은 변경되도 리렌더링을 일으키지 않는다. 따로 render 함수를 만들어서 변경된 값을 화면에 표시하도록 해줘야 한다. 즉, 변경된 데이터를 화면에 그리고 싶다면 데이터가 업데이트될때마다 render 함수를 호출해야만 한다.

useState hook

여기서 state의 개념이 들어온다.

const [state, setState] = useState();
// state -> 데이터를 담는 객체
// setState -> 데이터를 업데이트시킨 후 컴포넌트를 자동으로 리렌더해주는 함수

useState 훅을 이용하면 데이터를 담는 객체인 state와 그 데이터를 변경하고 리렌더해주는 setState 함수를 사용할 수 있다.

setState 함수는 데이터가 바뀔때마다 컴포넌트를 리렌더링하고 UI를 새로 그려준다.
데이터가 바뀌면 해당 컴포넌트 전체가 리렌더링이 되지만 브라우저 화면에 그릴 때는 virtual DOM을 통해 변경된 데이터만 다시 그려진다.

이제 useState 훅을 사용해서 항목이름을 변경해보자.

function ExpenseItem({ title, amount }) {
  const [displayTitle, setDisplayTitle] = useState(title);

  const clickHandler = () => setDisplayTitle("생수");

  return (
    <div>
      <div>
        <h2>항목: {displayTitle}</h2>
        <div>금액: ${amount}</div>
      </div>
      <button onClick={clickHandler}>변경</button>
    </div>
  );
}

export default ExpenseItem;

state가 업데이트되면서 자동으로 화면에도 업데이트된 데이터가 표시되는 것을 확인할 수 있다.

profile
얼레벌레 프론트엔드 개발자

0개의 댓글