드디어 데이터를 가져와보자..
Fake Store API
Fake store rest api for your ecommerce or shopping website prototype
fakestoreapi.com
이걸 사용해서 가져올거다.
1. CardList 컴포넌트 생성
import React, { useEffect } from 'react'
import { useAppDispatch, useAppSelector } from '../../../hooks/redux'
import CardItem from '../card-list/card-item/CardItem'
import styles from '../card-list/CardList.module.scss'
const CardList = () => {
const dispatch = useAppDispatch();
const {products} = useAppSelector((state) => state.productsSlice);
useEffect(()=>{
dispatch(fetchProducts());
},[])
return (
<ul className={styles.card_list}>
{products.map((item)=><CardItem key={index} item={item}/>)}
</ul>
)
}
export default CardList
- 처음 렌더링될 때 useEffect 훅을 통해 fetchProducts 액션을 디스패치한다.
- 비동기 요청을 트리거하여 제품 데이터를 가져옵니다.
2. store/ products.slice.js 생성
extraReducer
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";
export const fetchProducts = createAsyncThunk(
//아래에
)
const initialState ={
products:[],
isLoading:false,
error:"",
}
export const productsSlice = createSlice({
name:'products',
initialState,
reducer:{},
//extraReducers에 케이스 리듀서를 추가하면
//프로미스 진행 상태에 따라서 리듀서를 실행할 수 있다.
extraReducers:(builder) =>{
builder
.addCase(fetchProducts.pending,(state)=> {
state.isLoading =true;
})
.addCase(fetchProducts.fulfilled,(state,action)=> {
state.isLoading =false;
state.products = action.payload;
})
.addCase(fetchProducts.rejected,(state)=>{
state.isLoading =false;
state.error = action.payload;
})
},
})
이게 끝이 아니고 데이터를 불러와야하는데 ..
이 코드 위쪽에 주석 부분에 작성한다.
createAsyncThunk
export const fetchProducts = createAsyncThunk(
"products/fetchProducts",
async (thunkAPI) =>{
console.log(thunkAPI);
try{
console.log("@@데이터확인 : ",response);
return response.data ;//payload
}catch(error){
return thunkAPI.rejectWithValue("Error loading products 데이터요청 중 에러")
}
}
);
Redux toolkit 에서 비동기요청을 할 때 사용해준다.
자동으로 pending, fulfilled, rejected 상태를 관리해 준다.
- fetchProducts는 createAsyncThunk를 사용해 정의된 비동기 함수로,
- axios를 사용해 https://fakestoreapi.com/products API에서 제품 데이터를 가져온다
+ 추가: thunkAPI 객체의 유용한 기능
- dispatch: 추가로 다른 액션을 디스패치할 수 있습니다.
- getState: 현재 상태를 가져올 수 있습니다.
- rejectWithValue: 실패 시 사용자가 정의한 오류 메시지를 반환합니다.
3. 리듀서 등록해야함!!
products.slice.js
export const productsSlice = createSlice({
name:'products',
initialState,
reducer:{},
//extraReducers에 케이스 리듀서를 추가하면
//프로미스 진행 상태에 따라서 리듀서를 실행할 수 있다.
extraReducers:(builder) =>{
builder
.addCase(fetchProducts.pending,(state)=> {
state.isLoading =true;
})
.addCase(fetchProducts.fulfilled,(state,action)=> {
state.isLoading =false;
state.products = action.payload;
})
.addCase(fetchProducts.rejected,(state)=>{
state.isLoading =false;
state.error = action.payload;
})
},
})
💥💥 export default productsSlice.reducer;
그리고
store/ index.js에 등록 해준다.
import { configureStore } from "@reduxjs/toolkit";
import userReducer from "./user/user.slice";
import categoriesReducer from "./categories/categories.slice";
import productsReducer from "./products/products.slice";
export const store = configureStore({
reducer: {
user: userReducer,
category: categoriesReducer,
💥products: productsReducer,
},
});
그러면 이제 redux state에서 데이터들이 저장된게 보인다.
이제 그럼 데이터는 다 불러와지고, UI에 보여줘야한다.
4. 장바구니 cart.slice.js 생성
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
products:[],
totalPrice:0,
userId:""
}
export const cartSlice = createSlice({
name:"cart",
initialState,
reducers:{
}
})
export default cartSlice.reducer;
똑같이 slice 만들고,
그리고 리듀서 등록
import { configureStore } from "@reduxjs/toolkit";
import userReducer from "./user/user.slice";
import categoriesReducer from "./categories/categories.slice";
import productsReducer from "./products/products.slice";
import cartReducer from "./cart/cart.slice";
export const store = configureStore({
reducer: {
user: userReducer,
category: categoriesReducer,
products: productsReducer,
💥 cart: cartReducer
},
});
5. CardItem 컴포넌트 구현
import React from 'react'
import styles from '../card-item/CardItem.module.scss';
import { Link } from 'react-router-dom';
import { useAppSelector } from '../../../../hooks/redux';
const CardItem = ({item}) => {
const {products} = useAppSelector(state =>state.cart) 💥
const productMatching = products.some((product) =>product.id === item.id)
// 💥some() : 주어진 판별함수를 적어도 하나라도 통과하는지 테스트 -> true
return (
<li className={styles.card_item}
<Link to={`/products/${item.id}`}>
<img
src={item.image}
width={"80%"}
height={"200px"}
alt='product card'
/>
</Link>
<h5>{item.title.substring(0,15)}...</h5>
<div>
<button disabled={productMatching}>
//💥하나라도 같다면 (장바구니에 있다면) disable=true로
{productMatching? "장바구니에 잠긴 제품" : "장바구니에 담기"}
</button>
<p>$ {item.price}</p>
</div>
</li>
)
}
export default CardItem
그러면
요기까지 완성하였습니다 ~~~~
'⛲ 프로젝트 > 👖gproro-shop-app' 카테고리의 다른 글
[ gproro-shop-app] 로그인여부로 분기처리 with redux (0) | 2024.11.14 |
---|---|
[gproro-shop-app] 장바구니 기능 with Redux (0) | 2024.11.14 |
[gproro-shop-app] 카테고리별 데이터 가져오기 + 스켈레톤 UI (0) | 2024.11.12 |
[gproro-shop-app] category 컴포넌트 구현 with Redux (1) | 2024.11.12 |
[gproro-shop-app]리덕스로 로그인 , 회원가입 준비하기 (0) | 2024.11.12 |