mock 데이터는 실제 API에서 받아온 데이터가 아닌 프론트엔드 개발자가 필요에 의해 샘프롤 만들어본 데이터를 의미한다.
function ReviewListItem({ item }) {
return (
<div className="ReviewListItem">
<img className="ReviewListItem-img" src={item.imgUrl} alt={item.title} />
<div>
<h1>{item.title}</h1>
<p>{item.rating}</p>
<p>{formatDate(item.createdAt)}</p>
<p>{item.content}</p>
</div>
</div>
);
}
function ReviewList({ items }) {
return (
<ul>
{items.map((item) => {
return (
<li>
<ReviewListItem item={item} />
</li>
);
})}
</ul>
);
}
'최신순', '베스트순'으로 배열을 정렬하기 위해 sort 메소드를 사용한다.
function App() {
const [order, setOrder] = useState('createdAt');
const sortedItems = items.sort((a, b) => b[order] - a[order]);
const handleNewestClick = () => setOrder('createdAt');
const handleBestClick = () => setOrder('rating');
return (
<div>
<div>
<button onClick={handleNewestClick}>최신순</button>
<button onClick={handleBestClick}>베스트순</button>
</div>
<ReviewList items={sortedItems} />
</div>
);
}
function App() {
const [order, setOrder] = useState('createdAt');
const [items, setItems] = useState(mockItems);
const sortedItems = items.sort((a, b) => b[order] - a[order]);
const handleNewestClick = () => setOrder('createdAt');
const handleBestClick = () => setOrder('rating');
const handleDelete = (id) => {
const nextItems = items.filter((item) => item.id !== id);
setItems(nextItems);
};
return (
<div>
<div>
<button onClick={handleNewestClick}>최신순</button>
<button onClick={handleBestClick}>베스트순</button>
</div>
<ReviewList items={sortedItems} onDelete={handleDelete} />
</div>
);
}
요소들의 순서가 바뀔 때 엉뚱한 곳에 렌더링될 수 있으므로 key를 지정해 주어야 한다.
function ReviewList({ items, onDelete }) {
return (
<ul>
{items.map((item) => {
return (
<li key={item.id}>
<ReviewListItem item={item} onDelete={onDelete} />
</li>
);
})}
</ul>
);
}
key의 값으로는 고유한 값을 지정해 주어야 한다.
key를 사용하여 고유한 값으로 정해주면 배열의 변화를 정확하게 전해줄 수 있게 된다.
배열 메소드 map에서 콜백 함수의 리턴 값으로 리액트 엘리먼트를 리턴하면 된다.
import items from './pokemons';
function Pokemon({ item }) {
return (
<div>
No.{item.id} {item.name}
</div>
);
}
function App() {
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<Pokemon item={item} />
</li>
))}
</ul>
);
}
export default App;
반드시 JSX의 중괄호 안에서 map 함수를 써야 하는 것은 아니다. 아래처럼 renderedItems라는 변수에 map의 결과를 지정해도 똑같이 렌더링하게 된다. renderedItems의 계산된 값이 결국 리액트 엘리먼트의 배열이기 때문이다.
import items from './pokemons';
function Pokemon({ item }) {
return (
<div>
No.{item.id} {item.name}
</div>
);
}
function App() {
const renderedItems = items.map((item) => (
<li key={item.id}>
<Pokemon item={item} />
</li>
));
return (
<ul>
{renderedItems}
</ul>
);
}
export default App;
배열 메소드 sort로 정렬한 배열을 렌더링 할 수 있다. id 순서대로 / 반대로 정렬하는 예시이다.
import { useState } from 'react';
import items from './pokemons';
function Pokemon({ item }) {
return (
<div>
No.{item.id} {item.name}
</div>
);
}
function App() {
const [direction, setDirection] = useState(1);
const handleAscClick = () => setDirection(1);
const handleDescClick = () => setDirection(-1);
const sortedItems = items.sort((a, b) => direction * (a.id - b.id));
return (
<div>
<div>
<button onClick={handleAscClick}>도감번호 순서대로</button>
<button onClick={handleDescClick}>도감번호 반대로</button>
</div>
<ul>
{sortedItems.map((item) => (
<li key={item.id}>
<Pokemon item={item} />
</li>
))}
</ul>
</div>
);
}
export default App;
배열 메소드 filter와 배열형 스테이트를 활용하면 삭제 기능을 간단히 구현할 수 있다.
import { useState } from 'react';
import mockItems from './pokemons';
function Pokemon({ item, onDelete }) {
const handleDeleteClick = () => onDelete(item.id);
return (
<div>
No.{item.id} {item.name}
<button onClick={handleDeleteClick}>삭제</button>
</div>
);
}
function App() {
const [items, setItems] = useState(mockItems);
const handleDelete = (id) => {
const nextItems = items.filter((item) => item.id !== id);
setItems(nextItems);
};
return (
<ul>
{items.map((item) => (
<li key={item.id}>
<Pokemon item={item} onDelete={handleDelete} />
</li>
))}
</ul>
);
}
export default App;
각 요소를 렌더링 할 때는 key Prop을 내려줘야 한다. 이때 가장 바깥쪽에 있는 (최상위) 태그에다가 key Prop을 지정하면 된다. 앞에서 id는 각 요소를 구분할 수 있는 고유한 값이기 때문에 사용했지만, 반드시 id일 필요는 없고 각 데이터를 구분할 수 있는 고유한 값이면 무엇이든 key로 활용해도 상관없다.
import items from './pokemons';
function Pokemon({ item }) {
return (
<div>
No.{item.id} {item.name}
</div>
);
}
function App() {
return (
<ul>
{items.map((item) => (
<li key={item.name}>
<Pokemon item={item} />
</li>
))}
</ul>
);
}
export default App;