기본화면에서 음료 목록(home) 출력 후
추가버튼 누를 시 음료명과 설명 추가할 수 있는 폼 추가하기
필요한 기능 크게 구분해보자면
1. 목록 보기 / 목록 화면에서 삭제 버튼 누르면 삭제되는 기능 (Home)
2. 추가 버튼 눌렀을 때 음료명과 설명 input 폼으로 이동하기 (Create)
3. 링크 이동을 위한 BrowserRouter, Routes, Route, Link (App)
import 관련
import {
BrowserRouter,
Routes,
Route,
Link,
useNavigate,
} from "react-router-dom";
// NavLink는 Link랑 다르게 active 활성화 됨
import { useState } from "react";
import "./App.css"; // css 파일 연결
BrowserRouter: 브라우저의 주소 표시줄과 상호작용하여 다양한 경로로 이동할 수 있게 해줌
Routes/Route: BrowserRouter 내에서 경로와 전달할 props 명시하기 위해 필요
Link: a링크 대신 클릭했을 때 페이지 이동하도록 설정
useNavigate: 경로 이동
App
음료 추가 함수 / 음료 삭제 후 목록 다시 띄우기 함수 작성 후 Router 이용하여 컴포넌트에 props로 던짐
const App = () => {
const [id, setId] = useState(3);
const [beverages, setBeverages] = useState([
{
id: 1,
title: "여수 윤슬 헤이즐넛 콜드브루",
desc: "윤슬을 형상화한 헤이즐넛 콜드브루",
},
{
id: 2,
title: "아이스 오렌지 판타지 유스베리 티",
desc: "상큼한 오렌지와 유시베리, 얼그레이 티의 조화",
},
]);
const addBeverage = (title, desc) => {
console.log(title);
console.log(desc);
// 새로운 음료 객체 생성
// const newBeverage = {
// id: id,
// title: title,
// desc: desc,
// };
const newBeverage = { id, title, desc };
console.log(newBeverage);
setBeverages([...beverages, newBeverage]);
setId(id + 1);
};
const deleteBeverage = (id) => {
// 넘겨받은 id가 일치하지 않는 경우만 남겨서 새로운 리스트로 만듦
const newList = beverages.filter((item) => item.id !== parseInt(id));
setBeverages(newList);
};
return (
// 브라우저의 주소 표시줄과 상호 작용하여 다양한 경로로 이동할 수 있게 해줌
<BrowserRouter>
<h1>Cafe</h1>
<ul>
<li>
{/* Link: 홈 페이지(/)로 이동하도록 설정, localhost:3000/create */}
<Link to="/">목록</Link>
</li>
<li>
<Link to="/create">추가</Link>
</li>
</ul>
<Routes>
<Route
path="/"
element={<Home list={beverages} deleteBeverage={deleteBeverage} />}
// Home 컴포넌트에 beverages와 deleteBeverage props 전달
></Route>
{/* Create addBeverage={addBeverage} : 함수를 props로 던짐 */}
<Route path="/create" element={<Create addBeverage={addBeverage} />} />
</Routes>
</BrowserRouter>
);
};
Home
음료 목록 리스트, 삭제 기능(App에서 router로 받은 list, deleteBeverage 실행 후 목록 출력)
const Home = ({ list, deleteBeverage }) => {
console.log(list);
const onClick = (event) => {
console.log(event.target.id); // 삭제버튼 클릭 시 id값 출력
deleteBeverage(event.target.id);
};
return (
<>
{/* borderCollapse: "collapse" 테이블 border 1줄 처리 */}
<table border="1" style={{ borderCollapse: "collapse" }}>
<thead>
<tr>
<th>ID</th>
<th>음료명</th>
<th>설명</th>
<th>삭제</th>
</tr>
</thead>
{/* for문 대신 콜백함수 */}
<tbody>
{list.map((item) => (
<tr key={item.id}>
<td>{item.id}</td>
<td>{item.title}</td>
<td>{item.desc}</td>
<td>
<button onClick={onClick} id={item.id}>
삭제
</button>
</td>
</tr>
))}
</tbody>
</table>
</>
);
};
create
음료 추가 함수
const Create = ({ addBeverage }) => {
// const Create = (prop) => {
// console.log(prop); // 객체 방식으로 들어감 {addBeverage: ƒ}
// console.log(prop.addBeverage); 이렇게 받아야 하는데 복잡하니까
// 상단에서 바로 const Create = ({addBeverage}) => { 이렇게 객체방식으로 함수를 받아버림
// 추가하면 목록으로 이동하도록 navigate 추가
const navigate = useNavigate();
// App 컴포넌트에게 create 컴포넌트가 던질 수 없음(상위->하위 가능, 하위->상위 불가능)
const onSubmit = (event) => {
// 순식간에 끝나는 이벤트를 막음
event.preventDefault();
const title = event.target.title.value;
const desc = event.target.desc.value;
addBeverage(title, desc);
navigate("/");
};
return (
<>
<form onSubmit={onSubmit}>
<div>
{/* label for 쓸 경우 에러남 */}
<label htmlFor="title">음료명 : </label>
<input
type="text"
id="title"
name="title"
placeholder="음료명 입력"
/>
</div>
<div>
<label htmlFor="desc">설명 : </label>
<input type="text" id="desc" name="desc" placeholder="설명 입력" />
</div>
<input type="submit" value="추가" />
</form>
</>
);
};
'+ > React' 카테고리의 다른 글
bootstrap 개별 component 단위로 적용 (0) | 2023.09.21 |
---|---|
api 연결 후 카테고리 목록 띄우기 (0) | 2023.09.20 |
jsx, state 사용해서 click count (0) | 2023.09.19 |
react 세팅 및 Create React App 프로젝트 구조 (0) | 2023.09.19 |