Redux toolkit 적용해보기
Router적용과 axios로 get 요청까지는 해봤으니까 이제 받은 데이터를 저장할 상태를 만들기 위해 Redux toolkit을 적용해보기로 했다. Redux에 대한 개념까지는 어느정도 배웠는데 Redux toolkit은 처음 사용해 보는 것이어서 적용하고 상태 변경을 해 보는데 꽤 오랜 시간이 걸렸다.
내가 이해한 Redux toolkit의 상태 관리 흐름을 정리 해보려고 한다.
Redux의 큰 흐름은 다음과 같다. 사용화면 UI에서 상태를 변경하면
⓵ Action이라는 객체가 생성된다. Action 객체는 Reducer로 운반될 객체로 변경할 상태에 대한 정보가 담겨있다.
⓶ Dispatch라는 함수를 통해 Action객체가 Reducer라는 함수로 운반된다.
⓷ Reducer함수는 Store공간(상태를 저장해두는 곳) 내부에 등록되어 있는 함수로 상태를 변경해주는 함수이다.
⓸ Reducer함수에 의해 상태가 변경이 되고 그 상태는 Store에 저장된다.
⓹ 상태가 바뀌면 React가 상태변경을 감지하여 해당 컴포넌트를 리렌더링한다.
Reducer 만들기
Redux toolkit에서는 Reducer를 createSlice 메서드로 만든다.
// itemSlices.js
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios from "axios";
export const fetchEvent = createAsyncThunk("items", async () => {
const response = await axios.get(
"http://openapi.seoul.go.kr:8088/'인증키'/json/culturalEventInfo/1/6/"
);
return response.data;
});
const initialState = { value: "초기값" };
// 전체 아이템 저장
export const fullItemSlice = createSlice({
name: "fullItem",
initialState,
reducers: {},
extraReducers: (builder) => {
builder.addCase(fetchEvent.pending, (state) => {
state.loading = "pending";
});
builder.addCase(fetchEvent.fulfilled, (state, action) => {
state.loading = "succeeded";
state.value = { ...action.payload };
});
},
});
createSlice 인수로는 객체를 전달하고 객체 내부에 name(상태이름), initialState(초기상태), reducers, extraReducers 프로퍼티를 넣어준다.
지금은 일단 reducer에는 아무것도 만들지 않았다.
비동기 함수의 경우에는 그냥 reducer에 넣으면 안되고 extraReducers에 넣어 줘야 한다.
createAsyncThunk라는 메서드는 비동기 콜백을 받아서 action 객체를 만들어준다. 만들어진 action 객체를 dispatch함수로 reducer에 전달하면 extraReducer가 동작하면서 fetchEvent의 상태(pending,fulfilled, rejected)에 따라 state의 loading 프로퍼티에 상태를 저장하고 fulfilled 상태가 되면 받은 데이터를 fullItem의 value 프로퍼티에 저장한다.
loading 프로퍼티의 경우 조건부 렌더링에 활용할 수 있다.
rejected상태에 대한 코드는 일단은 나중에 넣을 예정이다.
Store 만들기
// store.js
import { configureStore } from "@reduxjs/toolkit";
import { fullItemSlice } from "./itemSlices";
export const store = configureStore({
reducer: {
fullItem: fullItemSlice.reducer
}
});
store는 configureStore라는 메서드를 통해 만든다. 여기에 객체 인자를 전달하는데 객채 내부에 reducer 프로퍼티 값에 객체를 만들고 거기에 이전에 만든 fullItemSlice.reducer를 등록하면 된다. fullItemSlice.reducer는 createSlice 메서드가 자동으로 만들어 주는 프로퍼티이다.
* 나중에 상태를 여러개 만들게 되면 전부 reducer의 프로퍼티로 등록하면 될 것 같다.
이렇게 만든 store를 index.js에 Provider로 등록한다.
//index.js
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import App from "./App";
import { store } from "./store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
이제 상태를 사용할 준비는 되었다.
useSelector
상태를 사용할 컴포넌트에 useSelector Hook을 사용하여 필요한 상태를 꺼내온다.
Dispatch
useDispatch hook을 사용하여 dispatch 함수를 만들고 action 객체를 인자로 전달하면 상태가 갱신된다.
이전에 만든 fetchEvent 라는 비동기 action객체를 전달하면 서울시 문화행사 정보를 상태에 저장할 수 있다.
// App.js
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import GlobalStyle from "./GlobalStyle";
import Nav from "./Components/Nav";
import MainPage from "./Pages/MainPage";
import Mine from "./Pages/Mine";
import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { fetchEvent } from "./itemSlices";
import DetailItem from "./Pages/DetailItem";
function App() {
const { value: fullItem } = useSelector((state) => state.fullItem);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchEvent());
}, []);
// dispatch(fetchEvent()); // 이거왜 무한루프돌지?
return (
<>
<GlobalStyle />
<Router>
<Nav />
<Routes>
<Route path="/" element={<MainPage />} />
<Route path="/Mine" element={<Mine />} />
<Route path="/DetailItem" element={<DetailItem />} />
</Routes>
</Router>
</>
);
}
export default App;
* 주의할 것!
dispatch 함수가 전달하는 상태와 useSelector 가 가져오는 상태가 같은 경우
dispatch와 useSelector가 같은 코드에 있으면 무한루프에 빠진다!
왜냐하면 dispatch가 action 객체를 보내면 - 상태가 변경되고 - 변경된 상태를 useSelector가 가져오면서 리렌더링되고 - dispatch가 다시 동작하면서 action객체를 보내고 - 상태가 변경되고 - ...... 를 반복하게된다!
무한루프 때문에 api 하루 천번 할당을 다써서 그날은 코딩을 더 하지 못했다....
이번 코드의 경우 처음에 한 번만 모든 데이터를 받아오면 되기 때문에 useEffect를 사용하여 처음 렌더링 할 때만 실행되도록 했다.
정리하다보니 Redux toolkit의 사용법을 어느정도 알것 같다.
다음 스텝은 Reducer를 사용하여 상태를 변경하는 작업을 해 볼 예정이다.
'토이 프로젝트 > 서울시문화행사' 카테고리의 다른 글
React로 웹페이지만들기 - 서울시 문화행사(6) (0) | 2023.03.13 |
---|---|
React로 웹페이지만들기 - 서울시 문화행사(5) (0) | 2023.03.11 |
React로 웹페이지 만들기 - 서울시 문화행사(4) (0) | 2023.03.06 |
React로 웹페이지 만들기 - 서울시 문화행사(2) (0) | 2023.03.02 |
React로 웹페이지 만들기 - 서울시 문화행사(1) (0) | 2023.02.27 |
댓글