[React] 조건부 컨텐츠: 삼항연산자, &&, 변수

summereuna🐥·2023년 3월 15일
0

React JS

목록 보기
34/69

조건부 컨텐츠는 각각 다른 상황에서 다양한 출력값을 렌더링하는 것이다.

✅ 삼항연산자

📚 조건(삼항)연산자
조건(삼항)연산자는 JavaScript에서 세 개의 피연산자를 받는 유일한 연산자이다.
앞에서부터 조건문, 물음표(?), 조건문이 참(truthy)일 경우 실행할 표현식, 콜론(:), 조건문이 거짓(falsy)일 경우 실행할 표현식이 배치된다.
해당 연산자는 if...else문의 대체재로 빈번히 사용된다.

function getFee(isMember) {
  return (isMember ? '$2.00' : '$10.00');
}
//
console.log(getFee(true));
// Expected output: "$2.00"
//
console.log(getFee(false));
// Expected output: "$10.00"
//
console.log(getFee(null));
// Expected output: "$10.00"

만약 filteredExpenses의 배열에 아무것도 들어있지 않을 때, 다른 컨텐츠를 출력하려면 어떻게 하면 될까?
조건식은 삼항연산자를 이용하여 구현할 수 있다.

return (
  {filteredExpenses.length === 0 ? (
   <div>지출한 비용이 없습니다.</div>
   ) : (
     filteredExpenses.map((expenses) => (
       <ExpenseItem]
         key={expenses.id}
         id={expenses.id}
         title={expenses.title}
         amount={expenses.amount}
         date={expenses.date}
         />
     ))
  )}
);

그런데 이렇게 긴 조건 표현식은 읽기 어려울 수 있다.
그럴 때 JS의 논리연산자를 사용할 수도 있다.

✅ &&연산자

📚 논리적 AND (&&) (논리적 연결) 연산자
앤드연산자는 모든 불리언 피연산자가 true가 되었을 때 해당 피연산자의 집합은 true가 된다.

  • 보다 일반적으로 왼쪽에서 오른쪽으로 평가할 때 연산자는 처음으로 만나는 거짓 같은 피연산자의 값을 반환한다. 혹은 모두 참 같은 값이라면 마지막 피연산자의 값을 반환한다.
  • AND 연산자는 불리언이 아닌 값을 보존하고 다음과 같이 반환한다.
result = '' && 'foo';  // result 에 ""(빈 문자열)이 할당된다.
result = 2 && 0;       // result 에 0 이 할당된다.
result = 'foo' && 4;   // result 에 4 가 할당된다.
  • 논리적 AND 표현식은 단락(short-circuit, 혹은 단축) 연산자이다.
    각 피연산자는 불리언으로 변환되므로, 어떤 변환이 false로 판별되면 AND 연산자는 그 즉시 멈추고 거짓으로 판별된 피연산자의 원래의 값을 반환한다. 나머지 피연산자는 평가하지 않는다.
(some falsy expression) && expr
//첫 번째 피연산자 (some falsy expression)은 거짓 같은 값으로 평가되기 때문에, expr 부분은 절대 평가되지 않는다.
// 만약 expr이 함수라면 해당 함수는 절대 실행되지 않는다.

이렇게 사용할 수 있다.

{filteredExpenses.length === 0 && <div>지출한 비용이 없습니다.</div>}
  1. filteredExpenses.length === 0true인 경우
    AND 연산자는 불리언이 아닌 값을 보존하고 반환한다. 따라서 첫번째 피연산자의 조건에 만족하면 앤드 연산자 다음 부분으로 이동하여 그 값인 JSX <div>지출한 비용이 없습니다.</div>를 반환한다. 즉, 필터링된 배열에 아무것도 들어있지 않은 경우 지출한 비용이 없다고 적힌 JSX를 반환된다.

  2. filteredExpenses.length === 0false 경우
    AND 표현식은 단락 연산자이기 때문에 첫번째 피연산자가 false로 판별되면 그 즉시 멈추고 나머지 피연산자는 평가하지 않는다. 즉, 필터링된 배열에 요소가 들어있다면 지출한 비용이 없다고 적힌 JSX는 반환되지 않는다.

이처럼 삼항연산자 표현식 대신 &&연산자를 사용하여 구현할 수도 있다.

{filteredExpenses.length === 0 && <div>지출한 비용이 없습니다.</div>}
//마찬가지! 필터링된 배열에 요소가 있을 때만 ExpenseItem을 렌더링하도록 표현식 작성
{filteredExpenses.length > 0 &&
  filteredExpenses.map((expenses) => (
    <ExpenseItem
      key={expenses.id}
      id={expenses.id}
      title={expenses.title}
      amount={expenses.amount}
      date={expenses.date}
      />
))}

하지만 이 코드도 JSX코드에 적기에는 과한 것 같다!

✅ 변수 추가하여 JSX 클린하게 유지하기

기존 JSX에 있던 로직을 변수로 만들어 컴포넌트 함수 자체로 끌어올려보자.
JSX 내부에서는 간단하게 동적 표현식을 추가하여 변수를 가리키면 된다.
그러면 가독성도 좋고, JSX 부분을 클린하게 유지할 수 있다.

import Card from "../UI/Card";
import "./Expenses.css";
import ExpenseItem from "./ExpenseItem";
import ExpensesFilter from "./ExpensesFilter";
import { useState } from "react";

const Expenses = (props) => {
  const [filteredYear, setFilteredYear] = useState("2020");

  const filterChangedYearHandler = (selectedYear) => {
    setFilteredYear(selectedYear);
  };

  const filteredExpenses = props.items.filter(
    (expense) => expense.date.getFullYear().toString() === filteredYear
  );

  //🔥 변수에 JSX 컨텐츠를 기본값으로 할당 및 저장할 수 있다.
  let expenseContent = <div>지출한 비용이 없습니다.</div>;
  
  //🔥 if문으로 체크
  if (filteredExpenses.length > 0) {
    //🔥 필터링된 배열에 요소가 있으면 ExpenseItem 컴포넌트를 매핑하는 로직으로 expenseContent를 오버라이드한다.
    expenseContent = filteredExpenses.map((expenses) => (
      <ExpenseItem
        key={expenses.id}
        id={expenses.id}
        title={expenses.title}
        amount={expenses.amount}
        date={expenses.date}
      />
    ));
  }

  return (
    <Card className="expenses">
      <ExpensesFilter
        onChangeFilterYear={filterChangedYearHandler}
        selected={filteredYear}
      />
      //🔥 JSX 내부에서는 간단하게 동적 표현식을 추가하여 expenseContent를 가리키면 된다.
      {expenseContent}
    </Card>
  );
};

export default Expenses;

결론

어떤 접근방법을 사용하든 상관 없지만, 가장 깔끔한 방법을 선택하자!
JSX 코드가 깔끔한게 좋으니 마지막 방법으로 고고~

profile
Always have hope🍀 & constant passion🔥

0개의 댓글