본문 바로가기

개발/React

[React] 조건부 렌더링과 리스트 렌더링

Step 0. 조건부 렌더링 (조건에 따라 화면에 보여주기)

React에서는 JavaScript 조건문을 이용해 화면을 바꾼다.

가장 간단한 방법은 삼항 연산자이다.

function App() {
  const isLoggedIn = true;

  return (
    <div>
      <h1>
        {isLoggedIn ? "환영합니다" : "로그인해주세요"}
      </h1>
    </div>
  );
}

export default App;

 

Step 1. 실제 요소 자체를 바꾸기

문자열만 바꿀 필요는 없다. 예를 들어, 버튼 자체를 바꿀 수 있다.

function App() {
  const isLoggedIn = true;

  return (
    <div>
      {isLoggedIn ? <button>로그아웃</button> : <button>로그인</button>}
    </div>
  );
}

export default App;

 

Step 2. && 를 이용한 조건부 렌더링

어떤 조건이 참일 때만 화면에 보여주고 싶을 수도 있다.

이런 경우에 && 연산자를 많이 사용한다.

function App() {
  const isAdmin = true;

  return (
    <div>
      <h1>마이페이지</h1>

      {isAdmin && <button>관리자 메뉴</button>}
    </div>
  );
}

export default App;

의미는

  • isAdmin이 true → 버튼 표시
  • isAdmin이 false → 아무것도 표시하지 않음

이다.

 

Step 3. State와 조건부 렌더링 연결하기

import { useState } from "react";

function App() {
  const [isLoggedIn, setIsLoggedIn] = useState(false);

  function toggleLogin() {
    setIsLoggedIn(!isLoggedIn);
  }

  return (
    <div>
      <h1>{isLoggedIn ? "환영합니다" : "로그인해주세요"}</h1>

      <button onClick={toggleLogin}>
        {isLoggedIn ? "로그아웃" : "로그인"}
      </button>
    </div>
  );
}

export default App;

버튼을 누르면

문자열과 버튼이 바뀌는 것을 볼 수 있다.

 

Step 4. 리스트 렌더링 (데이터 배열을 화면에 반복해서 보여주기)

실제 앱에서는 데이터가 여러 개 있는 경우가 많다.

예를 들어, 다음과 같은 사용자 목록이 있다고 하자.

const users = ["홍길동", "김철수", "이영희"];

이걸 직접 쓴다면

<ul>
  <li>홍길동</li>
  <li>김철수</li>
  <li>이영희</li>
</ul>

와 같이 작성해야 한다.

 

하지만 실제 앱에서는 데이터 개수가 계속 바뀔 수 있기 때문에 배열을 기반으로 UI를 만듭니다.

 

Step 5. map()

JavaScript의 map()은 배열의 각 값을 변환한다.

const numbers = [1, 2, 3];

const result = numbers.map((number) => number * 2);

// 결과: [2, 4, 6]

 

React에서는 다음과 같이 사용한다.

const users = ["홍길동", "김철수", "이영희"];

function App() {
  return (
    <ul>
      {users.map((user) => (
        <li>{user}</li>
      ))}
    </ul>
  );
}

export default App;

배열의 각 요소를 JSX 코드로 변환하여 UI로 만든다.

 

Step 6. 객체 배열 렌더링하기

실제 데이터는 문자열보다는 객체 형태가 많다.

function App() {
  const users = [
    {
      id: 1,
      name: "홍길동",
      job: "프론트엔드 개발자",
    },
    {
      id: 2,
      name: "김철수",
      job: "백엔드 개발자",
    },
    {
      id: 3,
      name: "이영희",
      job: "디자이너",
    },
  ];

  return (
    <div>
      {users.map((user) => (
        <div>
          <h2>{user.name}</h2>
          <p>{user.job}</p>
        </div>
      ))}
    </div>
  );
}

export default App;

 

Step 7. Key

위 코드를 실행해보면 개발자 도구의 Console에서 Each child in a list should have a unique "key" prop. 와 같은 경고를 볼 수 있다.

즉, React에서 리스트를 렌더링할 때 각 항목에는 key가 필요하다.

 

그러므로 다음과 같이 작성한다.

{users.map((user) => (
  <div key={user.id}>
    <h2>{user.name}</h2>
    <p>{user.job}</p>
  </div>
))}

지금 학습 단계에서는 key를 "React가 리스트의 각 항목을 구분하기 위한 고유한 값"이라고 이해하면 된다.

 

Step 8. 컴포넌트와 map 합치기

컴포넌트와 map()을 연결해보자.

function User({ name, job }) {
  return (
    <div>
      <h2>{name}</h2>
      <p>{job}</p>
    </div>
  );
}

function App() {
  const users = [
    {
      id: 1,
      name: "홍길동",
      job: "프론트엔드 개발자",
    },
    {
      id: 2,
      name: "김철수",
      job: "백엔드 개발자",
    },
    {
      id: 3,
      name: "이영희",
      job: "디자이너",
    },
  ];

  return (
    <div>
      {users.map((user) => (
        <User key={user.id} name={user.name} job={user.job} />
      ))}
    </div>
  );
}

export default App;

 

구조

데이터 배열
   ↓
map()
   ↓
Component 생성
   ↓
Props 전달
   ↓
화면 렌더링

실제 React 코드에서 굉장히 자주 보는 중요한 패턴이다.

 

Step 9. 빈 배열 처리하기

조건부 렌더링과 리스트 렌더링을 합치면 된다.

function App() {
  const users = [];

  return (
    <div>
      {users.length === 0 ? (
        <p>등록된 사용자가 없습니다.</p>
      ) : (
        <ul>
          {users.map((user) => (
            <li key={user.id}>
              {user.name}
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default App;

 

Step 10. 메모 목록 만들어보기

이번에는 아직 메모를 추가하는 기능까지는 넣지 않은 단순히 데이터를 출력하는 메모 목록을 만들어보자.

function App() {
  const memos = [
    {
      id: 1,
      text: "React 공부하기",
    },
    {
      id: 2,
      text: "운동하기",
    },
    {
      id: 3,
      text: "책 읽기",
    },
  ];

  return (
    <div>
      <h1>메모 목록</h1>

      <ul>
        {memos.map((memo) => (
          <li key={memo.id}>{memo.text}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

 

 

실습

이번에는 직접 다음 화면에 대한 코드를 작성해보자.

 

데이터는 다음 코드를 사용한다.

const products = [
  {
    id: 1,
    name: "맥북",
    price: 200,
    isSoldOut: false,
  },
  {
    id: 2,
    name: "키보드",
    price: 15,
    isSoldOut: true,
  },
  {
    id: 3,
    name: "마우스",
    price: 8,
    isSoldOut: false,
  },
];

 

 

답안

function App() {
  const products = [
    {
      id: 1,
      name: "맥북",
      price: 200,
      isSoldOut: false,
    },
    {
      id: 2,
      name: "키보드",
      price: 15,
      isSoldOut: true,
    },
    {
      id: 3,
      name: "마우스",
      price: 8,
      isSoldOut: false,
    },
  ];

  return (
    <div>
      <h1>상품 목록</h1>
      {products.map((product) => (
        <div key={product.id}>
          <h2>{product.name}</h2>
          <p>가격: {product.price}만원</p>
          <p>{product.isSoldOut ? "품절" : "판매중"}</p>
        </div>
      ))}
    </div>
  );
}

export default App;

 

 

한 단계 더 중요한 실습

이번에는 useState를 결합해보자.

import { useState } from "react";

function App() {
  const [memos, setMemos] = useState([
    {
      id: 1,
      text: "React 공부하기",
    },
    {
      id: 2,
      text: "운동하기",
    },
  ]);

  return (
    <div>
      <h1>메모 목록</h1>

      {memos.length === 0 ? (
        <p>메모가 없습니다.</p>
      ) : (
        <ul>
          {memos.map((memo) => (
            <li key={memo.id}>{memo.text}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default App;

여기서 중요한 변화로 전에는

const memos = [...]

였지만 이번에는

const [memos, setMemos] = useState([...]);

이다. 

 

왜 State로 만들었냐면 앞으로 메모를 추가, 삭제, 수정할 것이기 때문이다.

이제 화면에서 변화하는 데이터라면 State로 관리할 필요가 생긴 것이다.