Redux
react global state management library
Redux
component에 종속되지 않고 global state management를 합니다. props지옥을 탈출할 수 있습니다.
Flux pattern
redux는 기본적으로 flux 패턴을 따릅니다.
Action -> Dispatch -> Store -> View
Installation
yarn add redux react-redux redux-devtools-extension @reduxjs/toolkit
Reducer definition
reducer는 꼭 불변성을 지켜야 합니다. 그래야 redux가 이전 상태와 바뀐 상태를 구분할 수 있습니다. 왜냐하면 참조 값이 바뀌었는지를 가지고 변경 여부를 판단하고, 바뀌었다고 판단해야 re-render가 일어납니다.
Root reducer definition
// libraries import { applyMiddleware, combineReducers, compose, createStore } from 'redux'; import { composeWithDevTools } from 'redux-devtools-extension'; // customs import branchManagementReducer from 'modules/branch/reducer/branchManagement.reducer'; const rootReducer = combineReducers({ branchManage: branchManagementReducer, }); const middleware = applyMiddleware(); const enhancer = process.env.NEXT_PUBLIC_ENV_NODE === 'production' ? compose(middleware) : composeWithDevTools(middleware); export const store = createStore(rootReducer, enhancer);
detailed reducer definition
// store/counter.js const SET_DIFF = 'counter/SET_DIFF'; const INCREASE = 'counter/INCREASE'; const DECREASE = 'counter/DECREASE'; export const setDiff = diff => ({ type: SET_DIFF, diff }); export const increase = () => ({ type: INCREASE }); export const decrease = () => ({ type: DECREASE }); const initialState = { number: 0, diff: 1 }; export default function counter(state = initialState, action) { switch(action.type) { case SET_DIFF: return { ...state, diff: action.diff }; case INCREASE: return { ...state, number: state.number + state.diff }; case DECREASE: return { ...state, number: state.number - state.diff }; default: return state; } }
전역 컴포넌트에 store 생성하고 반영하기
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import { Provider } from 'react-redux'; import store from 'store'; // import './excercise'; ReactDOM.render( <React.StrictMode> <Provider store={store}> <App /> </Provider> </React.StrictMode>, document.getElementById('root') ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
Root reducer definition
// libraries import { configureStore } from '@reduxjs/toolkit'; // customs import branchManagementReducer from 'modules/branch/reducer/branchManagement.reducer'; export const store = configureStore({ reducer: { branchManage: branchManagementReducer, }, devTools: process.env.NEXT_PUBLIC_ENV_NODE !== 'production', });
detailed reducer definition
// libraries import { createSlice } from '@reduxjs/toolkit'; interface State { brandInfoDetail: { [key: string]: unknown; }; } const initialState: State = { brandInfoDetail: {}, }; const slice = createSlice({ name: 'branchManagement', initialState, reducers: { updateBranchInfoDetail(state, action) { state.brandInfoDetail = action.payload; }, }, }); export const { updateBranchInfoDetail } = slice.actions; export default slice.reducer;
dispatch
```typescript
redux-persist는 browser storage에도 저장하여 새로고침하여도 데이터가 유실되지 않는 라이브러리 입니다.
Installation
yarn add redux-persist
Configure
// store/index.js
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { persistStore, persistReducer } from 'redux-persist';
// import storage from 'redux-persist/lib/storage'; // local storage
import storageSession from 'redux-persist/lib/storage/session';
import counter from './counter';
import todos from './todos';
// 전역으로 persist 쓰고자 할
// const persistConfig = {
// key: 'root',
// storage: storageSession,
// // whitelist: [], // whitelist에 있는 값들만 persist한다.
// // blacklist: [], // blacklist에 있는 거 빼고 전부 persist한다.
// };
const persistConfig = {
key: 'counter',
storage: storageSession,
// whitelist: [], // whitelist에 있는 값들만 persist한다.
// blacklist: [], // blacklist에 있는 거 빼고 전부 persist한다.
};
const rootReducer = combineReducers({
counter: persistReducer(persistConfig, counter),
todos
});
// const persistedReducer = persistReducer(persistConfig, rootReducer); // 전역으로 persist쓰고자 할 때
const middlewares = []; // 미들웨어들을 넣으면 된다.
const enhancer =
process.env.NEXT_PUBLIC_NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(applyMiddleware(...middlewares));
const configureStore = () => {
let store = createStore(rootReducer, enhancer);
let persistor = persistStore(store);
return { store, persistor }
}
export default configureStore;
// _app.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react'
import configureStore from './store';
const { store, persistor } = configureStore();
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
redux-toolkit
Last updated
Was this helpful?