https://light9639.github.io/Redux-Toolkit-Axios-AsyncThunk/
โจ Redux-Toolkit์ AsyncThunk ๊ธฐ๋ฅ์ Axios๋ก ๊ตฌํํ ์ฐ์ต ํ์ด์ง์ ๋๋ค. โจ
- React ์์ฑ
npm create-react-app my-app
# or
yarn create react-app my-app
- vite๋ฅผ ์ด์ฉํ์ฌ ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ ค๋ฉด
npm create vite@latest
# or
yarn create vite
- ํฐ๋ฏธ๋์์ ์คํ ํ ํ๋ก์ ํธ ์ด๋ฆ ๋ง๋ ํ React ์ ํ, Typescirpt ์ ํํ๋ฉด ์์ฑ ์๋ฃ.
- Redux-Toolkit ์ค์น ๋ช ๋ น์ด
npm install redux react-redux @reduxjs/toolkit
# or
yarn add redux react-redux @reduxjs/toolkit
- axios ์ค์น ๋ช ๋ น์ด
npm install axios
# or
yarn add axios
react-redux
์์Provider
ํจ์ ๊ฐ์ ธ์จ ํstore.ts
ํ์ผ์import
ํ ํ<Provider store={store}></Provider>
์ผ๋ก<App />
์ ๋๋ฌ์ธ๋ฉดRedux-Toolkit
์ฌ์ฉ์ค๋น ์๋ฃ.
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import { Provider } from 'react-redux'
import { store } from './redux/store'
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
)
redux
ํจ์๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉดuseSelector
,useDispatch
๋ฅผimport
ํ ๋ค์ ์ฌ์ฉํ๋ฉด ๋๋ค.- ๊ทธ๋ฌ๋ ์์ 2๊ฐ์ง ํจ์๋ค์
type
์ ์ฉ์ด ์ ๋์ด ์๊ธฐ ๋๋ฌธ์useTypedSelector.ts
์useAppDispatch
,useAppSelector
๋ฅผ ๊ฐ์ ธ์์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข๋ค.
import { useSelector, useDispatch } from "react-redux";
import { fetchUser } from "./redux/userSlice";
import React, { useEffect } from "react";
import { RootState } from "./redux/store";
import { Dispatch } from "redux";
import { useAppDispatch, useAppSelector } from "./hooks/useTypedSelector";
export default function App(): JSX.Element {
const dispatch = useAppDispatch();
// RootState๊ฐ useSelector์์ state์ ํ์
์ผ๋ก ์ฌ์ฉ๋ ๊ฒ
const { users, loading, error } = useAppSelector(state => state.users);
return (
<div className="App" style={{ margin: "0 auto", textAlign: "center" }}>
<h1>Redux-tookit with Thunk</h1>
<button onClick={() => dispatch(fetchUser())} style={{ display: "inline-block", padding: "10px 15px", borderRadius: "5px" }}>์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ</button>
{users?.length > 0 &&
users.map((user) =>
<div key={user.index} style={{ textAlign: "center", margin: "0 auto" }}>
<img src={user.src} alt={user.alt} style={{ display: "block", maxWidth: "300px", margin: "25px auto", borderRadius: "15px" }} />
{user.name}
</div>
)}
</div>
)
}
Redux-toolkit
์ ๋ด์ฅ ๊ธฐ๋ฅ์ธcreateAsyncThunk
๋ฅผ ์์ฑ ํextraReducers
์์ฑํ๊ฒ ๋๋ฉดaxios
๋ฅผ ํตํ ์๋ฃ ์ ์ก์ด ๊ฐ๋ฅํด์ง๋ค.
import { createAsyncThunk, createSlice, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios";
import { store } from "./store";
import { CommonType } from "../Type/TypeBox";
interface initialType {
users: CommonType[],
loading: boolean,
error: string | undefined
}
const initialState: initialType = {
users: [],
loading: false,
error: ""
}
export const fetchUser = createAsyncThunk(
'counterSlice/asyncUpFetch',
async () => {
return axios({
method: "get",
url: "https://raw.githubusercontent.com/light9639/Shoe-Store/main/data/Shoes.json"
}).then(response => response.data.Kids);
}
)
// slice ์์ฑ
const usersSlice = createSlice({
// slice ์ด๋ฆ ์ ์
name: "users",
// ์ด๊ธฐ ๊ฐ
initialState,
// ๋ฆฌ๋์
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchUser.pending, (state) => {
state.loading = true;
}),
builder.addCase(fetchUser.fulfilled, (state, action) => {
state.users = action.payload;
state.loading = false;
}),
builder.addCase(fetchUser.rejected, (state, action: PayloadAction<any>) => {
state.loading = false;
})
}
});
// useSelector ์ฌ์ฉ์ ํ์
์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํจ
export type RootState = ReturnType<typeof store.getState>
// useDispatch๋ฅผ ์ข ๋ ๋ช
ํํ๊ฒ ์ฌ์ฉํ๊ธฐ ์ํจ
export type AppDispatch = typeof store.dispatch
// slice๋ฅผ ๋ด๋ณด๋
export default usersSlice.reducer;
configureStore
์์userSlice
์reducer
๋ฅผ ๊ฐ์ ธ์จ ํexport
ํจ์ผ๋ก์จ ํจ์๋ฅผ ์ฌ์ฉ ๊ฐ๋ฅํ๊ฒ ํจ.
import { configureStore } from "@reduxjs/toolkit";
import { useDispatch } from 'react-redux';
import userReducer from "./userSlice";
export const store = configureStore({
reducer: {
users: userReducer
}
});
useDispatch
,useSelector
์ ํ์ ์ ๋ฒ๋ฒํ ์ง์ ํ๊ธฐ๋ณด๋คuseAppDispatch
,useAppSelector
๋ฅผ ์ ์ฅํ๊ณimport
ํจ์ผ๋ก์จtype
์ง์ ์ ์๊ณ ๋ฅผ ๋ ์ ์๋ค.
import { useDispatch, useSelector } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { RootState, AppDispatch } from "../redux/store";
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
axios
๋ก ๊ฐ์ ธ์ฌ ๋ฐ์ดํฐ์ ํ์ ์ง์ .
export type CommonType = {
index: number;
src: string;
alt: string;
name: string;
info: string;
price: string;
Gender: string;
href: string;
star: {
first: string;
second: string;
third: string;
four: string;
five: string;
};
Review: number;
count: number;
}
- ์ถ์ฒ 1 : Redux-Toolkit ํํ์ด์ง
- ์ถ์ฒ 2 : Velog ๊ธ