کانفیگ Redux و Redux-Saga در Next.js

در این مقاله قصد دارم نصب و کانفیگ redux و redux-saga رو در فریم‌ورک ری‌اکت Next.js به شما آموزش بدم.

نصب

yarn add redux react-redux next-redux-wrapper redux-saga next-redux-saga

اگر نیاز به فعال سازی اکستنشن مرورگر redux dev tools را دارید دستور زیر را هم در خط فرمان اجرا کنید.

yarn add -D redux-devtools-extension

کانفیگ Store

یک فایل برای مثال در root پروژه خود با نام store.js ایجاد کنید و خطوط زیر رو درون اون بنویسید.

import { applyMiddleware, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import createSagaMiddleware from 'redux-saga';

import rootReducer from './reducers'; // combineReducers({..., ...})
import rootSaga from './sagas'; // yield all([fork(...), ...])

const bindMiddleware = (middleware) => {
  if (process.env.NODE_ENV !== 'production') {
    return composeWithDevTools(applyMiddleware(...middleware));
  }
  return applyMiddleware(...middleware);
};

const configureStore = (initialState) => {
  const sagaMiddleware = createSagaMiddleware();
  const store = createStore(
    rootReducer,
    initialState,
    bindMiddleware([sagaMiddleware])
  );
  store.sagaTask = sagaMiddleware.run(rootSaga);
  return store;
};
export default configureStore;

خب یه توضیح کوتاه راجب کانفیگ بالا بدم.

  • خطوط 1 تا 3 واسه import کتابخانه‌های redux و redux-dev-tools و redux-saga هستن
  • در خط 5 یک فایل با نام reducers رو import کردم که درون این فایل تمامی reducer های من با هم combine شدن
  • در خط 6 یک فایل دیگه برای saga با نام sagas ایمپورت کردم که درون این فایل تمامی saga های پروژه با هم fork شدن
  • من bindMiddleware رو به صورت یک تابع تعریف کردم، شاید روش دیگه‌ای شما دوست داشته باشین تعریفش کنین، خلاصه ... در صورتی که شما در mode ای غیر از production، برای مثال در حالت development باشید، redux-dev-tools وارد عمل شده و redux شما را تحت شعاع خودش قرار میده
  • در ادامه هم که saga middleware رو به middleware های store اضاف و در نهایت create store کردم.
  • اون sagaTask هم که به آبجکت store متصل کردم بعدها بدردمون میخوره.

نیم نگاهی به فایل reducers.js

import { combineReducers } from 'redux';
import userReducer from '../scenes/User/store/User.reducer';

const rootReducer = combineReducers({
  user: userReducer
  // add other reducers to the array
});
export default rootReducer;

و نیم نگاهی به فایل sagas.js

import { all, fork } from 'redux-saga/effects';
import user from '../scenes/User/store/User.saga';

/**
  * @description Notice how we now only export the rootSaga,
  *  single entry point to start all Sagas at once.
  * @example rootSaga();
  */
export default function* rootSaga() {
  try {
    yield all([
      fork(user)
      // add other watchers to the array
    ]);
  } catch (e) {}
}

کانفیگ Next.js

خب حالا به سراغ کانفیگ Next.js برای Redux می‌ریم، فایل _app.js در دایرکتوری pages رو باز کنید و به شکل زیر اون رو کانفیگ کنید. (اگر این فایل وجود نداره، ایجادش کنید)

// /pages/_app.js

import { Provider } from 'react-redux';
import withRedux from 'next-redux-wrapper';
import withReduxSaga from 'next-redux-saga';

import createStore from '../store';

class MyApp extends App {

  // For Server Side Rendering
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {};
    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps({ context: ctx });
    }
    return { pageProps };
  }
  
  render() {
    const { Component, pageProps, store } = this.props;
    return (
      <Container>
        <Provider store={store}>
          <Component {...pageProps} />
        </Provider>
      </Container>
    );
  }
}
export default withRedux(createStore)(withReduxSaga(MyApp));


در مقاله‌های بعدی سعی میکنم تعریف یک action و dispatch کردن اون رو در saga بهتون آموزش بدم و همینطور آموزش dispatch کردن action ها در حالت SSR برای Next.js