React 컴포넌트의 상태 유지 : 삼항 연산자 vs 논리 연산자

2023. 4. 26. 23:24·개념정리/React

React에서 상태(state)는 컴포넌트의 라이프사이클 동안 정보를 유지하는데 사용되는 중요한 개념입니다. useState 훅을 이용하여 컴포넌트의 상태를 관리하면, 상태가 변경될 때마다 컴포넌트가 다시 렌더링 됩니다. 그런데, 상황에 따라서 컴포넌트의 상태가 유지되거나 초기화되는 경우가 있는데, 이는 컴포넌트가 렌더링 되는 방식에 따라 달라집니다.

삼항 연산자(? :)와 논리 연산자(&&)를 이용하여 컴포넌트를 렌더링 하는 경우, 두 연산자가 UI 트리(가상 DOM)에 미치는 영향은 서로 다릅니다. 이로 인해 React의 diffing 알고리즘이 컴포넌트를 다르게 인식하고 처리하며, 결론적으로 컴포넌트의 상태 유지에서 차이가 나게 됩니다.

삼항 연산자와 컴포넌트의 상태

삼항 연산자를 사용하면, 두 표현식 중 하나만 렌더링 되지만, 이 둘은 동일한 위치에 렌더링 되기 때문에, React는 이들을 같은 컴포넌트로 인식합니다. 따라서, 삼항 연산자를 사용하여 렌더링 된 컴포넌트의 상태는 유지됩니다.

예를 들어, 다음과 같은 코드에서는 Counter 컴포넌트의 상태가 유지됩니다.

import { useState } from 'react';

export default function Scoreboard() {
  const [isPlayerA, setIsPlayerA] = useState(true);
  return (
    <div>
      {isPlayerA ? (
        <Counter person="Taylor" />
      ) : (
        <Counter person="Sarah" />
      )}
      <button onClick={() => {
        setIsPlayerA(!isPlayerA);
      }}>
        Next player!
      </button>
    </div>
  );
}

function Counter({ person }) {
  const [score, setScore] = useState(0);
  const [hover, setHover] = useState(false);

  let className = 'counter';
  if (hover) {
    className += ' hover';
  }

  return (
    <div
      className={className}
      onPointerEnter={() => setHover(true)}
      onPointerLeave={() => setHover(false)}
    >
      <h1>{person}'s score: {score}</h1>
      <button onClick={() => setScore(score + 1)}>
        Add one
      </button>
    </div>
  );
}

https://codesandbox.io/s/suspicious-river-t9gcp8?file=/App.js

 

suspicious-river-t9gcp8 - CodeSandbox

suspicious-river-t9gcp8 by boonke using react, react-dom, react-scripts

codesandbox.io

위 코드에서 isPlayerA 값에 따라서 다른 person prop을 받지만, 실제로는 동일한 Counter 컴포넌트로 인식되므로 상태도 유지됩니다.

 

논리 연산자와 컴포넌트의 상태

논리 연산자를 사용하면, 조건이 참일 때만 표현식이 렌더링 됩니다. 따라서 조건이 바뀔 때마다 표현식은 새로운 위치에 렌더링 되는 것으로 React에게 인식됩니다. 이로 인해 컴포넌트가 언마운트되고 새로운 컴포넌트가 마운트 되는 것처럼 보입니다. 따라서, 논리 연산자를 사용하여 렌더링 된 컴포넌트의 상태는 초기화됩니다.

다음과 같은 코드에서는 Counter 컴포넌트의 상태가 초기화됩니다.

import { useState } from 'react';

export default function Scoreboard() {
  const [isPlayerA, setIsPlayerA] = useState(true);
  return (
    <div>
      {isPlayerA &&
        <Counter person="Taylor" />
      }
      {!isPlayerA &&
        <Counter person="Sarah" />
      }
      <button onClick={() => {
        setIsPlayerA(!isPlayerA);
      }}>
        Next player!
      </button>
    </div>
  );
}

function Counter({ person }) {
  const [score, setScore] = useState(0);
  const [hover, setHover] = useState(false);

  let className = 'counter';
  if (hover) {
    className += ' hover';
  }

  return (
    <div
      className={className}
      onPointerEnter={() => setHover(true)}
      onPointerLeave={() => setHover(false)}
    >
      <h1>{person}'s score: {score}</h1>
      <button onClick={() => setScore(score + 1)}>
        Add one
      </button>
    </div>
  );
}

https://codesandbox.io/s/modest-rgb-32sti1?file=/App.js

 

modest-rgb-32sti1 - CodeSandbox

modest-rgb-32sti1 by boonke using react, react-dom, react-scripts

codesandbox.io

위 코드에서 isPlayerA 값에 따라 다른 Counter 컴포넌트가 렌더링 되지만, 두 Counter 컴포넌트는 서로 다른 위치에 렌더링 되므로 각각 별도의 인스턴스로 처리되어 상태가 초기화됩니다.

 

결론

React는 JSX 마크업에서가 아닌 UI 트리에서의 위치에 관심이 있다는 것을 기억하고 연산자에 따라서 위치를 다르게 인식할 수 도 있다는 점을 주의해서 적절히 활용하자!

 

레퍼런스

https://react.dev/learn/preserving-and-resetting-state

저작자표시 비영리 변경금지 (새창열림)
'개념정리/React' 카테고리의 다른 글
  • Zustand는 왜 이렇게 동작할까?(내부 구현 열어보기)
  • 리액트 동시성 렌더링을 알아보자
  • React에서 Proxy 설정하기
  • 번들링과 웹팩
imKion
imKion
Front-end Developer
  • imKion
    Kion
    imKion
  • 전체
    오늘
    어제
    • 분류 전체보기 (46)
      • 문제 해결 (6)
        • 리팩터링 (3)
      • 회고 (8)
      • 개념정리 (29)
        • JavaScript (10)
        • React (9)
        • Next.JS (2)
        • WEB (5)
        • CS 외 (2)
      • 알고리즘 (2)
        • 코플릿 (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    코드스테이츠
    typeScript
    til
    JavaScript
    프론트엔드
    REACT
    react 18
    회고
    frontend
    OOP
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
imKion
React 컴포넌트의 상태 유지 : 삼항 연산자 vs 논리 연산자
상단으로

티스토리툴바