routes 폴더 안에 Cart.js 파일을 생성하여 다음 코드를 작성한다.
import { Table } from "react-bootstrap";
function Cart() {
return (
<div>
<Table responsive="md">
<thead>
<tr>
<th>#</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
<tr>
<td>2</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
<tr>
<td>3</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
</tbody>
</Table>
</div>
);
}
export default Cart;
기본 테이블 레이아웃이다.
App.js 파일에 적당한 위치에 다음 코드를 추가한다.
.
.
import Cart from "./routes/Cart";
.
.
<Route path="/cart" element={<Cart />} />
이제 /cart 페이지로 접속하면 테이블 구조를 볼 수 있다.
redux 설치
근데 설치하기 전에 package.json 파일을 열어서 "react" ,"react-dom" 항목의 버전을 확인합시다.
이거 두개가 18.1.x 이상이면 사용가능하다.
npm install @reduxjs/toolkit react-redux
store.js 에서 state 등록/사용하는 방법
import { configureStore, createSlice } from "@reduxjs/toolkit";
const user = createSlice({
name: "user",
initialState: "kim",
});
export default configureStore({
reducer: {
user: user.reducer,
},
});
name: "user"
👉 state 이름
initialState: "kim"
👉 state 초기값
reducer: {
user: user.reducer,
}
👉 state 등록
state 사용할 Component 안에서 다음 코드를 적으면 store.js 안에 있는 모든 state 를 사용할 수 있다.
const store = useSelector((state) => {
return state;
});
redux state 수정하는 방법
- state 변경해주는 함수 만들기
- export
- dispatch(1번에서 만듬 함수())
이제 기본적인 redux 사용법을 배웠으니 실제로 장바구니에 데이터를 담아보고 수량을 증가시키는 버튼을 만들어보자.
아래는 장바구니 데이터를 직접 적어서 넣고 수량(count) state 변경까지 적용한 코드이다.
(store.js)
/* eslint-disable */
import { configureStore, createSlice } from "@reduxjs/toolkit";
const user = createSlice({
name: "user",
initialState: { name: "kim", age: 21 },
});
const cart = createSlice({
name: "cart",
initialState: [
{ id: 0, name: "White and Black", count: 2 },
{ id: 2, name: "Grey Yordan", count: 1 },
],
reducers: {
changeCount(state, action) {
const i = state.findIndex((product) => product.id === action.payload);
state[i].count += 1;
},
},
});
export const { changeCount } = cart.actions;
export default configureStore({
reducer: {
user: user.reducer,
cart: cart.reducer,
},
});
changeCount(state, index)
👉 state는 현재 state 값이고 index는 아래 코드의 dispatch(변수)의 변수값이다.
아래는 테이블에 state를 가져와서 데이터바인딩 하는 코드이다.
(Cart.js)
/* eslint-disable */
import { Table } from "react-bootstrap";
import { useDispatch, useSelector } from "react-redux";
import { changeCount } from "../store";
function Cart() {
const state = useSelector((state) => state);
const dispatch = useDispatch();
return (
<div>
<h5>{state.user.name}님의 장바구니</h5>
<Table responsive="md">
<thead>
<tr>
<th>#</th>
<th>상품명</th>
<th>수량</th>
<th>변경하기</th>
</tr>
</thead>
<tbody>
{state.cart.map((item, index) => {
return (
<tr key={index}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td>
<button
onClick={() => {
dispatch(changeCount(item.id));
}}
>
+
</button>
</td>
</tr>
);
})}
</tbody>
</Table>
</div>
);
}
export default Cart;
+버튼을 누르면 그 상품의 수량이 증가하는 걸 확인할 수 있다.
이제 상품상세화면에서 장바구니 버튼을 클릭할 때 장바구니에 상품을 담는 기능과 장바구니 페이지에서 물품을 삭제하는 기능을 구현해보자.
우선 cart state 관련 코드가 길어질 것 같으니 store.js에서 cart 부분은 따로 빼자.
store 폴더를 만들고 그 안에 cartSlice.js 파일을 만든다.
다음 코드를 넣는다.
import { createSlice } from "@reduxjs/toolkit";
const cart = createSlice({
name: "cart",
initialState: [
{ id: 0, name: "White and Black", count: 2 },
{ id: 2, name: "Grey Yordan", count: 1 },
],
reducers: {
changeCount(state, action) {
const i = state.findIndex((product) => product.id === action.payload);
state[i].count += 1;
},
addItem(state, action) {
const pd = {
id: action.payload.id,
name: action.payload.title,
count: 1,
};
state.push(pd);
},
deleteItem(state, action) {
const i = state.findIndex((product) => product.id === action.payload);
state.splice(i, 1);
},
},
});
export const { changeCount, addItem, deleteItem } = cart.actions;
export default cart;
addItem, deleteItem 모두 state 변경하는 과정 그대로 하면 된다.
Detail.js 에서 장바구니 버튼 부분을 아래처럼 수정해준다.
<button
className="btn btn-danger"
onClick={() => {
const index = state.cart.findIndex(
(pd) => pd.id === shoe[0].id
);
if (index < 0) {
dispatch(addItem(shoe[0]));
} else {
dispatch(changeCount(shoe[0].id));
}
}}
>
장바구니
</button>
Cart.js 도 다음과 같이 수정해주자.
.
.
<tbody>
{state.cart.map((item, index) => {
return (
<tr key={index}>
<td>{item.id}</td>
<td>{item.name}</td>
<td>{item.count}</td>
<td>
<button
onClick={() => {
dispatch(changeCount(item.id));
}}
>
+
</button>
</td>
<td>
<button
onClick={() => {
dispatch(deleteItem(item.id));
}}
>
x
</button>
</td>
</tr>
);
})}
</tbody>
.
.
import 할 건 찾아서 하면 된다.
장바구니에 이미 있는 상품이면 수량을 추가해주고 없는 상품일때만 상품을 새로 장바구니에 추가해준다고 생각하고 코드를 짰다.
지금까지 페이지들을 모두 연동하기 위해 몇가지 수정을 좀 해주자.
(App.js)
.
.
return (
<div className="App">
<Navbar bg="dark" variant="dark">
<Container>
<Navbar.Brand
onClick={() => {
navigate("/");
}}
>
My shop
</Navbar.Brand>
<Nav className="me-auto">
<NavDropdown title="About" id="navbarScrollingDropdown">
<NavDropdown.Item
onClick={() => {
navigate("/about/member");
}}
>
member
</NavDropdown.Item>
<NavDropdown.Item
onClick={() => {
navigate("/about/location");
}}
>
location
</NavDropdown.Item>
</NavDropdown>
<Nav.Link
onClick={() => {
navigate("/cart");
}}
>
Cart
</Nav.Link>
</Nav>
</Container>
</Navbar>
<Routes>
<Route path="/" element={<Home shoes={shoes} />} />
<Route path="/detail/:id" element={<Detail shoes={shoes} />} />
<Route path="/cart" element={<Cart />} />
<Route path="/about" element={<About />}>
<Route path="member" element={<div>멤버정보</div>} />
<Route path="location" element={<div>위치정보</div>} />
</Route>
<Route path="*" element={<div>없는 페이지입니다.</div>} />
</Routes>
{btnShow == true ? <button onClick={btnMore}>더보기</button> : null}
{loading == true ? <p>로딩중입니다.</p> : null}
</div>
);
.
.
(Shoe.js)
.
.
<img
src={"https://codingapple1.github.io/shop/shoes" + i + ".jpg"}
width="80%"
onClick={() => {
console.log("home");
navigate(`/detail/${item.id}`);
}}
/>
.
.
이제 지금까지 구현한 기능들을 모두 페이지로 이동하고 서로 연동되는 것을 확인할 수 있게 되었다.

