mock.json 파일에 영화 리뷰 관련 데이터들이 있다.
function formatDate(value) {
const date = new Date(value);
return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
}
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>
);
}
export default ReviewList;
import ReviewList from "./ReviewList";
import items from "../mock.json";
function App() {
return (
<div>
<ReviewList items={items} />
</div>
);
}
export default App;
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./components/App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
꼭 중괄호 안에서 map을 써야 하는 것은 아니고 변수에 지정해서 사용할 수도 있다.
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;
작은 순서대로 정렬: numbers.sort((a, b) => a - b)
크기가 큰 순서대로 정렬: numbers.sort((a, b) => b - a)
import ReviewList from "./ReviewList";
import items from "../mock.json";
import { useState } from "react";
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>
);
}
export default App;
import "./ReviewList.css";
function formatDate(value) {
const date = new Date(value);
return `${date.getFullYear()}. ${date.getMonth() + 1}. ${date.getDate()}`;
}
function ReviewListItem({ item, onDelete }) {
const handleDeleteClick = () => onDelete(item.id);
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>
<button onClick={handleDeleteClick}>삭제</button>
</div>
</div>
);
}
function ReviewList({ items, onDelete }) {
return (
<ul>
{items.map((item) => {
return (
<li>
<ReviewListItem item={item} onDelete={onDelete} />
</li>
);
})}
</ul>
);
}
export default ReviewList;
import { useState } from "react";
import ReviewList from "./ReviewList";
import mockItems from "../mock.json";
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>
);
}
export default App;
배열을 렌더링 할 때는 반드시 key를 설정해줘야 한다.
배열의 인덱스는 키로 사용할 수 없다.
각 데이터를 구분할 수 있는 고유한 값으로 지정해야 한다.
배열의 결과를 리액트에 정확히 반영하기 위해서 key를 사용해야 한다.
가방 바깥쪽에 있는 (최상위) 태그에다가 key Prop을 지정하면 된다.
function ReviewList({ items, onDelete }) {
return (
<ul>
{items.map((item) => {
return (
<li key={item.id}>
<ReviewListItem item={item} onDelete={onDelete} />
</li>
);
})}
</ul>
);
}
위 예시에서는 id값이 고유한 값이기 때문에 키로 정했다.