렌더링 제어
포스트
취소

렌더링 제어

조건부 렌더링

조건부 렌더링(conditional rendering)이란?

  • 조건부 설정을 통해서 상황에 맞게 렌더링하는 것
  • 종류
    • if/else 조건문
    • 삼항 연산자
    • 논리 AND 연산자 (&&)

if / else 조건문

  • 조건문의 결과에 따라 렌더링 여부가 결정된다.
  • null을 반환하면 아무것도 렌더링하지 않는다.
    • 실제로 컴포넌트에서 null을 반환하도록 구현하는 것은 좋지 않다.
    • 부모 컴포넌트의 JSX에서 조건부로 해당 컴포넌트를 포함하거나 제외하는 것이 좋다.
  • 예시
const SampleButton = ({ name, isActive }) => {
  if (isActive) {
    return <button>{name}</button>;
  }
  return null;
};

const Sample = (props) => {
  return (
      <>
        <SampleButton isActive={true} name="활성화" />
        <SampleButton isActive={false} name="비활성화" />
      </>
    );
};

export default Sample;

삼항 연산자

  • 삼항 연산자를 통해 조건에 맞게 랜더링한다.
  • 삼항 연산자 문법
    • 조건 ? 조건의 결과가 참일 경우 : 조건의 결과가 거짓일 경우
  • 예시
const SampleButton = ({ name, isActive }) => {
  return isActive ? <button>{name}</button> :  null;
};

const Sample = (props) => {
  return (
      <>
        <SampleButton isActive={true} name="활성화" />
        <SampleButton isActive={false} name="비활성화" />
      </>
    );
};

export default Sample;

논리 AND 연산자 (&&)

  • 자바스크립트의 논리 AND 연산자(&&)를 사용하여 조건부 렌더링을 할 수도 있다.
  • 주로 React 컴포넌트 내부에서 특정 값을 만족하는 경우에만 렌더링시키고 싶을 때 사용하는 방법이다.
  • 예시
const SampleButton = ({ name, isActive }) => {
  return isActive && <button>{name}</button>;
};

const Sample = (props) => {
  return (
      <>
        <SampleButton isActive={true} name="활성화" />
        <SampleButton isActive={false} name="비활성화" />
      </>
    );
};

export default Sample;

배열 렌더링

map()을 활용한 배열 렌더링

  • 자바스크립트 배열 객체의 map() 메소드를 사용한다.
  • 컴포넌트를 반복하여 랜더링하고 싶을 때 사용한다.
  • map() 문법
    • 배열.map((현재 원소[, 현재 인덱스[, 원본 배열]]) => {})
  • 예시
const monthArr = [
  "1월", "2월", "3월", "4월", "5월", "6월", "7월", "8월", "9월", "10월", "11월", "12월"
];

const Sample = (props) => {
  const List = monthArr.map((str) => <li>{str}</li>);
  return (
      <>
        <h1>map() 메소드를 통한 배열 렌더링 테스트</h1>
        <ul>{List}</ul>
      </>
    );
};

export default Sample;

key prop 설정

  • React에서는 엘리먼트 리스트를 만들 때 각 아이템마다 고유한 key를 지정해야 한다.
  • key를 통해 해당 리스트에 저장된 아이템 간의 식별을 안정적으로 수행할 수 있다.
  • key를 통해 어떤 아이템이 변경/추가/삭제되었는지를 빠르게 파악할 수 있다.
  • 잘 선택된 key는 React가 리스트에 무슨 일이 일어났는지를 파악하고, DOM 트리를 정확하게 업데이트하는 데 많은 도움을 줄 수 있다.
  • key 값은 같은 리스트에 포함된 아이템 사이에서만 고유한 값을 가지면 된다.
    • 전체 애플리케이션이나 단일 컴포넌트 전체를 모두 통틀어 고유한 값일 필요는 없다.
    • 다른 리스트에서 같은 key 값을 사용하는 것은 전혀 문제되지 않는다.
  • 일반적으로 key는 해당 데이터가 가지고 있는 고유한 값(id)을 사용하는 것이 가장 좋다.
    • 데이터베이스로부터 가지고 온 데이터라면 DB의 key 값이나 id 값을 사용하는 것이 좋다.
    • 게시판 데이터라면 게시물 id 등을 key로 사용하는 것이 좋다.
  • key는 React가 아이템을 추가/제거 또는 다시 정렬할 시기를 결정할 수 있도록 리렌더링 시 안정적으로 식별 가능한 값이어야 합니다.
    • 절대 Math.random()과 같이 랜덤한 값을 key로 사용해서는 안 된다.
  • React에서는 리스트 아이템에 key를 명시적으로 지정하지 않으면, 기본적으로 index 값을 key로 사용한다.
    • index 값을 key로 사용하는 것은 애플리케이션의 성능 저하나 컴포넌트의 state와 관련된 문제가 발생할 수 있기 때문에 권장하지 않는다.
  • 배열 내부의 원소가 정렬되면 인덱스도 변경된다.
  • 예시
const items = [
  { id: 0, text: "치킨" }, { id: 1, text: "피자" }, { id: 2, text: "족발" }
];

const Sample = (props) => {
  const List = items.map((item, index) => <li key={item.id}>{item.text}</li>);
  return (
      <>
        <h1>map() 메소드를 통한 배열 렌더링 테스트</h1>
        <ul>{List}</ul>
      </>
    );
};

export default Sample;

아이템 추가 및 삭제

  • 아이템 추가
    • React에서는 참조 타입인 객체나 배열의 경우 반드시 불변성이 지켜져야만 한다.
      • 배열에 새로운 원소를 추가할 때는 배열 객체의 push() 메소드를 사용해서는 안 된다.
      • push() 메소드는 메소드를 호출한 원본 배열의 마지막부터 새로운 원소를 추가하므로 바로 이 불변성을 위반하게 된다.
    • React에서는 concat() 메소드를 사용하여 새로운 원소가 추가된 새로운 배열을 생성한다.
    • 단순히 배열명.concat()을 실행하면 배열이 복사되기만 한다.
    • 배열명.concat(원소)를 실행하면 새로운 원소가 추가된다.
      • 배열명.concat(원소1, 원소2, 원소3)처럼 여러 개를 원소를 한꺼번에 추가할 수도 있다.
  • 아이템 삭제
    • filter() 메소드를 통해 true 값을 반환하는 원소들만 존재하는 새로운 배열을 반환받는다.
    • 만약 id가 3인 원소를 삭제하려면 콜백 함수에서 id가 3이 아닌 원소들만 반환받도록 작성하면 된다.
      • 예시 : const newItems = items.filter((name) => name.id !== id);
import { useState } from "react";

const Sample = () => {
  const [items, setItems] = useState([
    { id: 0, name: "Spring Boot" },
    { id: 1, name: "JPA" },
    { id: 2, name: "React" },
    { id: 3, name: "Computer Science" }
  ]);

  const [inputValue, setInputValue] = useState("");
  const [id, setId] = useState(4); //items의 id 설정용

  const onChange = (e) => setInputValue(e.target.value);

  const onAdd = () => {
    const newItems = items.concat({
      id: id,
      name: inputValue
    });
    setItems(newItems);
    setId(id + 1); //id 값 증가
    setInputValue(""); //input 초기화
  };

  const onRemove = (id) => {
    const newItems = items.filter((name) => name.id !== id);
    setItems(newItems);
  };

  const subjects = items.map((item) => <li key={item.id}>{item.name}<button onClick={() => onRemove(item.id)}>삭제</button></li>);

  return (
    <>
      <h1>공부할 목록</h1>
      <input value={inputValue} onChange={onChange} />
      <button onClick={onAdd}>추가하기</button>
      <ul>{subjects}</ul>
    </>
  );
};

export default Sample;
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.