사용 전 준비
# yarn 사용 시
yarn add redux react-redux @reduxjs/toolkit
# npm 사용 시
npm install redux react-redux @reduxjs/toolkit
Redux이란?
먼저 Redux는 상태 관리 라이브러리 중 하나로 현재까지 가장 많이 쓰이고 있다.
Redux를 사용하지 않으면 한 컴포넌트의 함수를 props 형태로 다른 컴포넌트로 전달하고, 또 그것을 props 형태로 다른 컴포넌트로 전달하는 과정을 반복해야한다.
이런 복잡한 구조는 불필요한 props 전달로 유지보수 또는 props 추적을 힘들게하는 Props drilling을 야기한다.
상태 관리 라이브러리는 이러한 문제들을 해결하기 위해 고안되었다.
Redux는 Reducer와 Store를 통해 상태 변경 과정을 간소화하여 기존의 문제를 해결했다. 이것은 복잡한 상태 관리를 매우 효율적이고 간편하게 변경하여 오류 발생률을 낮추게 한다.
Redux 관련 용어
- Store : 컴포넌트의 전역 상태를 관리하는 저장소다. 하나의 프로젝트는 하나의 store만 가질 수 있다.
- Action : store의 상태를 변경하기 위해서는, action을 생성해야한다. action은 객체이며, 반드시 type을 가져야 한다. action 객체는 action 생성함수에 의해서 만들어진다.
- Reducer : reducer는 현재 상태와 action 객체를 받아 새로운 상태를 리턴하는 함수다.
- Dispatch : dispatch는 store의 내장 함수 중 하나이며, action 객체를 넘겨줘 state를 업데이트 시켜주는 역할을 한다.
- Subscribe : 스토어의 내장 함수 중 하나로, 리듀서가 호출될 때 서브스크라이브된 함수 및 객체를 호출한다
Redux-toolkit이란?
redux-toolkit은 redux가 공식적으로 만든 라이브러리이며, 기존의 Redux를 더 쉽게 사용하기 위해 만들어졌다.
Redux는 Flux 아키텍처를 기반으로 잘 설계된 라이브러리이지만 다음과 같은 문제점을 보였다.
1) 리덕스의 복잡한 스토어 설정
2) 리덕스를 유용하게 사용하기 위해서 추가되어야 하는 많은 패키지들
3) 리덕스 사용을 위해 요구되는 다량의 상용구(boilerplate) 코드들
이러한 문제점을 개선하기 위해 Redux Toolkit이 만들어지게 되었다. Redux Toolkit에서 제공하는 주요 함수들을 사용하면 기존 리덕스의 복잡도를 낮추고 사용성을 높여서 코드를 작성할 수 있다.
Redux Toolki 가이드: https://redux-toolkit.js.org/introduction/getting-started
Redux-toolkit 사용하기
1. configureStore
- configureStore 함수는 Redux 라이브러리의의 createStore 함수를 추상화한 것
- 기존의 번거로웠던 Redux 설정을 간편하게 할 수 있도록 해주고 설정 시 디폴트로 redux-thunk와 DevTools를 제공해줌.
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { createLogger } from 'redux-logger';
import { UserSlice } from './UserSlice';
const logger = createLogger();
const rootReducer = combineReducers({
user: UserSlice.reducer,
todo: todoSlice.reducer,
});
const initialState = {};
export const store = configureStore({
reducer: rootReducer,
// middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger),
// devTools: process.env.NODE_ENV !== 'production',
// preloadedState: initialState,
// enhancers: (defaultEnhancers) => [...defaultEnhancers]
});
reducer
- Redux store의 rootReducer를 설정.
- combineReducers 함수를 사용하여 slice reducer들을 병합한 rootReducer를 설정 가능.
- 단일 함수로 설정한 경우엔 store의 rootReducer로 사용됨.
- slice reducer로 설정한 경우엔 자동으로 combineReducers에 전달하여 rootReducer를 생성.
middleware
- redux-logger와 같은 리덕스 미들웨어를 설정.
- 미들웨어를 설정한 경우엔 자동으로 applyMiddleware에 전달.
- 미들웨어를 설정하지 않은 경우엔 getDefaultMiddleware를 호출.
devTools
- Redux DevTools 사용 여부 설정. (기본값은 true)
preloadedState
- Redux store의 초기값 설정.
enhancers
- 사용자 정의 미들웨어를 설정.
- 콜백 함수로 설정하면 미들웨어 적용 순서를 정의 가능.
* configureStore에 대한 공식 문서: https://redux-toolkit.js.org/api/configureStore
2. createSlice
createSlice 함수는 선언한 slice의 name에 따라서 action 생성자, action 타입, reducer를 자동으로 생성해줌. 따라서 별도로 createAction이나 createReducer를 사용하지 않아도 됨.
slice를 생성할 때 Action 타입은 name이 앞에 붙은 형태(user/setUser, todo/setTodo)로 생성됨.
생성된 action 타입을 가진 action이 dispatch되면 reducer가 실행되게됨.
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
todoList: TodoItem[]
};
export const todoSlice = createSlice({
name: 'todo',
initialState,
reducers: {
setTodo(state, action) {
state.todoList = action.payload;
}
}
});
export const { setTodo } = todoSlice.actions;
export default todoSlice;
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
user: "0",
favorite: false,
active: ""
};
export const UserSlice = createSlice({
name: "user",
initialState,
reducers: {
setUser: (state, action) => {
state.user = action.payload;
},
setFavorite: (state, action) => {
state.active = action.payload
},
chgFavorite: (state, action) => {
state.favorite = !state.favorite
},
}
});
export const { setUser, setFavorite, chgFavorite } = UserSlice.actions;
3. Redux Toolkit을 적용한 상태 관리
- reducer를 가져오기 위해 useSelector() 사용
- reducer를 변경하기 위해 useDispatch() 사용
import { useDispatch } from 'react-redux';
const Todo = () => {
const dispatch = useDispatch();
const setStore = (setter, value) => setter(value);
const getStore = (slice, key) => useSelector(store => store[slice][key]);
// reducer 가져오기 - name이 user인 store에서 favorite의 상태를 가져옴.
const favorite = getStore("user", "favorite");
// reducer 변경하기 - chgFavorite 액션을 실행함.
const handleStar = useCallback(() => {
dispatch(setStore(chgFavorite));
})
const handleActive = useCallback(() => {
if (getActive === "active") { dispatch(setStore(setFavorite, "active")); }
else { dispatch(setStore(setFavorite, "")); }
})
}
4. index.js 파일에 Provicder 추가
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from 'react-router-dom';
import { Provider, Store } from '@services';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={Store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
);
Redux Toolkit 공식 문서: https://redux-toolkit.js.org/usage/usage-guide
'Web > React' 카테고리의 다른 글
[React] redux-persist를 통한 Store 유지하기 (0) | 2023.01.24 |
---|---|
React Hooks 정리 (0) | 2023.01.24 |