Redux Wrapper
- next-redux-wrapper
- Next.js와 같은 SSR은 서버에서 데이터를 사용하여 화면을 미리 만들게되는데 서버에 Redux 데이터를 사용하기 위해 연결하는 장치
$ npm i next-redux-wrapper
설정
- createWrapper: Next.js에서 사용하는 라이프사이클 (getServerSideProps, getStaticProps)과 Redux를 결합시킴으로써 접근가능하게 만듦
createWrapper(store, option)
option: {debug: boolean}
: 리덕스에 관한 상세정보들을 로깅
import { createWrapper } from 'next-redux-wrapper';
import { applyMiddleware, createStore, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import reducer from '../reducers';
import rootSaga from '../sagas';
const configureStore = (context) => {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const enhancer = process.env.NODE_ENV === 'production'
? compose(applyMiddleware(...middlewares))
: composeWithDevTools(
applyMiddleware(...middlewares),
);
const store = createStore(reducer, enhancer);
store.sagaTask = sagaMiddleware.run(rootSaga);
return store;
};
const wrapper = createWrapper(configureStore, {debug: process.env.NODE_ENV === 'development'});
export default wrapper;
reducer/index.js
- HTDRATE:
next-redux-wrapper
를 사용할 때 필요한 액션, 서버에서 실행된 리덕스 상태 결과물을 클라이언트에서 HYDRATE라는 액션을 통해 전달됨
import { HYDRATE } from 'next-redux-wrapper';
import { combineReducers } from 'redux';
import otherReducer from './other';
import other2Reducer from './other2';
const rootReducer = (state, action) => {
switch (action.type) {
case HYDRATE:
console.log('HYDRATE', action);
return action.payload;
default: {
const combineReducer = combineReducers({
otherReducer1,
otherReducer2,
});
return combineReducer(state, action);
}
}
}
export default rootReducer;
_app.js
- wrapper.withRedux(): Hight-Order-Component로 최상단 컴포넌트를 감싸주게되면 각 페이지의 next.js lifecylce에서 스토어에 접근이 가능해진다.
- Next.js는 기존 react에서 redux를 사용하기 위해 Provider로 감싸는 설정을 하지 않아도 자체적으로 제공해준다.
- 오히려 위의 설정을 해준다면 중복이기 때문에 설정하지 않는것을 추천
import wrapper from './store/configureStore';
const App = ({ Component }) => {
return (
<>
<Component />
</>
)
}
epxort default wrapper.withRedux(App);
Life Cycle Method 결합
- 화면을 그리기 전에 리덕스 데이터를 서버쪽에서 먼저 실행해주어야 한다.
- wrapper는
store/configureStore.js
에서 만들어둔 store를 감싼 객체
wrapper.getServerSideProps
에서 dispatch
한 결과물을 HYDRATE
로 전달하게 된다.
export const getServerSideProps = wrapper.getServerSideProps((store) => async ({req, res, ...etc}) => {
store.dispatch({
type: LOAD_MY_INFO_REQUEST,
});
store.dispatch({
type: LOAD_POSTS_REQUEST
})
store.dispatch(END);
await store.sagaTask.toPromise();
});