이전 시간
지금까지 표준 JS
의 map
method를 활용하여 동적으로 데이터를 출력하고, filter
method로 선택된 연도에 맞는 item
만 출력되도록 하는 코드를 작성했다.
그 코드는 아래와 같으며, 정상적으로도 작동한다.
import React, { useState } from "react";
import ExpensesFilter from "./ExpensesFilter";
import ExpenseItem from "./ExpenseItem";
import Card from "./../UI/Card";
import "./Expenses.css";
const Expenses = (props) => {
const [filterYear, setFilterYear] = useState("2020");
const filterChangeHandler = (selectedYear) => {
setFilterYear(selectedYear);
console.log(selectedYear);
};
const filteredExpenses = props.items.filter(
(expense) => expense.date.getFullYear().toString() === filterYear
);
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
{filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
));
}
</Card>
</div>
);
};
export default Expenses;
여기에 더 나아가 아무런 데이터가 없을 때, 선택된 연도에 해당하는 item
이 존재하지 않을 때, 다른 컨텐츠가 출력되도록 하고 싶다.
상황에 따라 A를, B를, C를 렌더링해야 하는 경우가 생기길 마련이다.
이런 경우, 어떻게 해야 좋을까?
삼항 연산자
여기 JSX코드에 동적인 표현식을 추가해주고 조건을 사용하면 된다.
이번 예시처럼 긴 구문은 중괄호{} 사이에서 사용할 수 없다.
대신 다른 방법이 있는데 그 중 하나가 삼항 연산자이다. 다음과 같이 사용되는 것을 삼항 연산자라고 부른다.
조건문 ? True일 때 : False일 때
아래 코드는 실제 적용 방법이다.
import React, { useState } from "react";
import ExpensesFilter from "./ExpensesFilter";
import ExpenseItem from "./ExpenseItem";
import Card from "./../UI/Card";
import "./Expenses.css";
const Expenses = (props) => {
const [filterYear, setFilterYear] = useState("2020");
const filterChangeHandler = (selectedYear) => {
setFilterYear(selectedYear);
console.log(selectedYear);
};
const filteredExpenses = props.items.filter(
(expense) => expense.date.getFullYear().toString() === filterYear
);
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
{filteredExpenses.length === 0 ? (
<p>No expenses found.</p>
) : (
filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))
)}
</Card>
</div>
);
};
export default Expenses;
물론, 이렇게 긴 조건부 표현식은 읽기 어려울 수 있다.
그래서 조정하거나 구조를 다시 바꿔서 조건을 다시 사용할 수 있지만 JavaScript의 요령을 사용할 수 있다.
논리 연산자를 활용한 단축 평가
이해를 돕기 위해 잘 설명되어 있는 blog를 참고바란다.
import React, { useState } from "react";
import ExpensesFilter from "./ExpensesFilter";
import ExpenseItem from "./ExpenseItem";
import Card from "./../UI/Card";
import "./Expenses.css";
const Expenses = (props) => {
const [filterYear, setFilterYear] = useState("2020");
const filterChangeHandler = (selectedYear) => {
setFilterYear(selectedYear);
console.log(selectedYear);
};
const filteredExpenses = props.items.filter(
(expense) => expense.date.getFullYear().toString() === filterYear
);
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
{filteredExpenses.length === 0 && <p>No expenses found.</p>}
{filteredExpenses.length > 0 &&
filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))}
</Card>
</div>
);
};
export default Expenses;
간단히 설명하자면 여기 &&
논리연산자를 활용한 JavaScript 표현식이다.
단축평가라고 말하며, 해당 표현의 해석은 &&
앞의 조건과 뒤의 조건에 있다.
만약 &&
앞에 나온 조건이 true를 반환하면 &&
뒤에 조건이 출력되어 렌더링 된다.
하지만 이런 코드는 JSX코드에게 과한 로직일 수 있다.
변수 추가하기
처음에 초기값으로 들어갈 내용을 저장해둔다.
JSX컨텐츠를 다음과 같이 저장할 수 있는데, 이로써 어느 곳에서나 반환하고 사용할 수 있게 된다.
컨텐츠를 반환하는 것 뿐만 아니라 변수에 저장되는 값을 설정하는 데에도 JSX는 제한없이 사용할 수 있다.
import React, { useState } from "react";
import ExpensesFilter from "./ExpensesFilter";
import ExpenseItem from "./ExpenseItem";
import Card from "./../UI/Card";
import "./Expenses.css";
const Expenses = (props) => {
const [filterYear, setFilterYear] = useState("2020");
const filterChangeHandler = (selectedYear) => {
setFilterYear(selectedYear);
console.log(selectedYear);
};
const filteredExpenses = props.items.filter(
(expense) => expense.date.getFullYear().toString() === filterYear
);
let expensesContent = <p>No expenses found.</p>;
if (filteredExpenses.length > 0) {
expensesContent = filteredExpenses.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
));
}
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
</Card>
{expensesContent}
</div>
);
};
export default Expenses;
위의 코드를 살펴보자
기본 값으로 출력되어야 할 내용을 expensesContent
에 초기값으로 할당해주었다.
앞서서 filteredExpenses
를 선언했기 때문에 filtering한 결과값이 이미 저장되어 있는 상태이다.
따라서 filteredExpenses
의 길이가 0보다 큰지 if
문으로 체크할 수 있게 되었다.
이런 방법을 사용한다면 return
에 포함된 JSX코드의 모든 로직을 제거할 수 있게 된다.
깔끔한 JSX 코드로 가독성을 높일 수 있다는 특징이 있다.
component 분리하기
해당 조건문은 로직을 추출하여 새로운 component로 만들 수 있다.
import React, { useState } from "react";
import Card from "./../UI/Card";
import ExpensesList from "./ExpensesList";
import ExpensesFilter from "./ExpensesFilter";
import "./Expenses.css";
const Expenses = (props) => {
const [filterYear, setFilterYear] = useState("2020");
const filterChangeHandler = (selectedYear) => {
setFilterYear(selectedYear);
console.log(selectedYear);
};
const filteredExpenses = props.items.filter(
(expense) => expense.date.getFullYear().toString() === filterYear
);
return (
<div>
<Card className="expenses">
<ExpensesFilter
selected={filterYear}
onChangeFilter={filterChangeHandler}
/>
<ExpensesList items={filteredExpenses}/>
</Card>
</div>
);
};
export default Expenses;
import React from "react";
import ExpenseItem from "./ExpenseItem";
import "./ExpensesList.css";
const ExpensesList = (props) => {
if (props.items.length === 0) {
return <h2 className="expenses-list__fallback">Found no expenses.</h2>;
}
return (
<ul className="expenses-list">
{props.items.map((expense) => (
<ExpenseItem
key={expense.id}
title={expense.title}
amount={expense.amount}
date={expense.date}
/>
))}
</ul>
);
};
export default ExpensesList;
항상 component를 만들 때에는 함수 형태이기 때문에 return
값이 존재해야한다.
만약 component의 return
값이 전부 바뀐다면, 다시 말해 새로운 형태의 component가 된다면, 이런 접근 방법을 사용할 수 있다.
이전 상황들에서는 해당 접근 방식은 사용할 수 없었지만, ExpensesList
와 같은 작은 component의 경우, return
값을 달리함으로써 조건부 컨텐츠를 처리했다.
조건이 되는 구문을 props로 상속받아 그에 따른 다른 처리 방식을 볼 수 있다.
이번 시간에는 여러 방법으로 조건문을 구현했다.
이전 코드와 마찬가지로 작동하며, 상황에 맞게 여러 접근 방식을 비교하며 선택하면 된다.