메인페이지 목록 출력
페이지에 접속 했을 때, 기본적으로 도서 목록을 표시해 주는 메인페이지.
Redux 비동기 feature 작성
Redux에서 비동기 통신을 활용할 것이다.
리덕스에 내장되어 있는 createAsyncThunk 을 사용한다.
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from '../api/axios'; // 커스텀 axios 호출
// createAsyncThunk('명칭/개요', 실행할 함수) 의 형태
export const fetchFrontEnd = createAsyncThunk('get/frontEnd',
async(_query, _page) => {
const res = await axios.get('', {
params: {
query: _query,
page: _page
}
})
if (res.data) {
return res.data.documents;
} else {
return console.error('오류 발생');
}
})
// books에 값을 저장할 것이다.
const initialState = {
books: [],
loading: 'Loading...'
}
const bookSlice = createSlice({
name: 'frontEnd',
initialState,
reducers : { },
extraReducers: (builder) => {
builder.addCase(fetchFrontEnd.fulfilled, (state, action) => {
state.books.push(action.payload)
})
}
})
// store.js
import { configureStore } from "@reduxjs/toolkit";
import frontEndReducer from './features/frontEnd';
export const store = configureStore({
reducer : {
frontEnd : frontEndReducer,
},
})
Slice 를 작성하여 활용하는 중, 불편한 상황에 직면했다.
// 호출 코드
import { useDispatch, useSelector } from 'react-redux';
import { fetchFrontEnd } from '../features/frontEnd';
const frontEnd = useSelector((store) => store.frontEnd.books);
const dispatch = useDispatch();
let pageCount = 1;
useEffect(() => {
dispatch(fetchFrontEnd('프론트엔드', pageCount));
}, [pageCount]);
console.log(frontEnd);
books가 배열로 감싸고, books에 배열묶음이 할당되는 것
순회하기에 복잡한 접근을 하게 된다.
그래서 initialState의 books에 값을 할당하는 로직을 수정한다.
// 수정 전
const bookSlice = createSlice({
name: 'frontEnd',
initialState,
reducers : { },
extraReducers: (builder) => {
builder.addCase(fetchFrontEnd.fulfilled, (state, action) => {
state.books.push(action.payload)
})
}
})
//수정 후
const bookSlice = createSlice({
name: 'frontEnd',
initialState,
reducers : { },
extraReducers: (builder) => {
builder.addCase(fetchFrontEnd.fulfilled, (state, action) => {
const bookList = action.payload;
[...bookList].map((book) => {
state.books.push(book) // 순회하여 하나씩 books에 push
})
})
}
})
- addCase는 fetchFrontEnd가 fulfilled를 반환할 경우, state와 action을 반환
- action은 아래와 같은 값을 지니고 있다.
- 우리가 필요한 것은 payload
- books에 배열 묶음을 push하는 것이 아니라, 순회하며 하나씩 push 하도록 변경
- 익숙한 배열의 형태를 받을 수 있다.
컴포넌트에 적용
이제 이것을 활용하여 목록을 순회하고 화면에 출력해주기만 하면 된다.
// BookList.js
return (
<section>
<WrapBookList>
<H2Title>도서 목록</H2Title>
<ListCategory>
<li><button type='button' name='frontend'>프론트엔드</button></li>
<li><button type='button' name='webDev'>웹개발</button></li>
<li><button type='button' name='webDesign'>웹디자인</button></li>
</ListCategory>
<SecFrontend>
<H3hide>프론트엔드 도서 목록</H3hide>
<ListBook>
{
frontEnd.map((book) => {
return (
<Book key={book.isbn} info={book} />
)
})
}
</ListBook>
</SecFrontend>
</WrapBookList>
</section>
)
Book 컴포넌트에 각각의 props를 내려준다.
(이 부분은 전역상태로 전달/관리하는 좋은 방법이 있을까?)
// Book.js
export default function Book({info}) {
const date = info.datetime.slice(0,10);
return (
<ItmeBook>
<button>
<WrapBook>
<WrapDetail>
<h4>{info.title}</h4>
<p>
{info.contents}
</p>
<small>{date}</small>
<strong>{info.price} 원</strong>
</WrapDetail>
<ImgBook src={info.thumbnail} alt='' />
</WrapBook>
</button>
</ItmeBook>
)
}
받은 props를 필요한 위치에 맞게 정보를 출력해주면 끝이다.
API 연결 후 페이지
'Development' 카테고리의 다른 글
리액트 폴더 구조(Architecture) (0) | 2023.01.08 |
---|---|
Chart.js 사용하기 (0) | 2022.12.19 |
도서 정리 프로젝트(3) (0) | 2022.06.13 |
도서 정리 프로젝트(2) (0) | 2022.06.12 |
도서 정리 프로젝트(1) (0) | 2022.06.11 |