1. Getting Started
2. Basic Concepts
3. Handlers
4. Advanced Concepts
Installation
# Installing on create-react-app scafolding
Note:Please make sure to install required dependencies.
npm install redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
If you are using yarn:
yarn add redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
/* index.js */import React from "react";import ReactDOM from "react-dom";import { Provider } from "react-redux";import { store as configureStore } from "react-boilerplate-redux-saga-hoc";import "./index.css";import App from "./App";import * as serviceWorker from "./serviceWorker";const initialState = {};const middleware = [];const store = configureStore(initialState, middleware);ReactDOM.render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>,document.getElementById("root"));// If you want your app to work offline and load faster, you can change// unregister() to register() below. Note this comes with some pitfalls.// Learn more about service workers: https://bit.ly/CRA-PWAserviceWorker.unregister();
/** App.js **/import React from "react";import { HOC as HocConfigure } from "react-boilerplate-redux-saga-hoc";import { compose } from "redux";import logo from "./logo.svg";import "./App.css";const HOC = HocConfigure({handlers: [],});const NewHoc = HOC({initialState: {profile: {},},dontReset: {TEST_API: {},TEST_SUB_API: {},},useHook: true,apiEndPoints: {TEST_API: {},TEST_SUB_API: {},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},constantReducer: ({ type, state }) => {if (type === "NAME")return {...state,name: "NAME",};return state;},name: "NAME2",});const AuthHoc = HOC({initialState: {profile: {},},dontReset: {TEST_API: {},},useHook: true,apiEndPoints: {TEST_API: {url: "https://jsonplaceholder.typicode.com/posts/",method: "GET",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "message",},TEST_SUB_API: {},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},constantReducer: ({ type, state }) => {if (type === "NAME")return {...state,name: "NAME",};return state;},name: "Auth",});function App(props) {console.log(props);React.useEffect(() => {const {Auth_hoc: {actions: { TEST_API_CALL },},} = props;TEST_API_CALL();}, []);return (<div className="App"><header className="App-header"><img src={logo} className="App-logo" alt="logo" /><p>Edit <code>src/App.js</code> and save to reload.</p><aclassName="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer">Learn React</a></header></div>);}export default compose(NewHoc, AuthHoc)(App);
# Installing on React-Boilerplate scafolding
npm install react-boilerplate-redux-saga-hoc
/*** app.js** This is the entry file for the application, only setup and boilerplate* code.*/// Needed for redux-saga es6 generator supportimport "@babel/polyfill";// Import all the third party stuffimport React from "react";import ReactDOM from "react-dom";import { Provider } from "react-redux";import { ConnectedRouter } from "connected-react-router";import { Router } from "react-router-dom";import FontFaceObserver from "fontfaceobserver";import history from "utils/history";import "sanitize.css/sanitize.css";// Import root appimport App from "containers/App";// Import Language Providerimport LanguageProvider from "containers/LanguageProvider";// Load the favicon and the .htaccess fileimport "!file-loader?name=[name].[ext]!./images/favicon.ico";import "file-loader?name=.htaccess!./.htaccess"; // eslint-disable-line import/extensionsimport configureStore from "./configureStore";// Import i18n messagesimport { translationMessages } from "./i18n";// Observe loading of Open Sans (to remove open sans, remove the <link> tag in// the index.html file and this observer)const openSansObserver = new FontFaceObserver("Open Sans", {});// When Open Sans is loaded, add a font-family using Open Sans to the bodyopenSansObserver.load().then(() => {document.body.classList.add("fontLoaded");});// Create redux store with historyconst initialState = {};const store = configureStore(initialState, history);const MOUNT_NODE = document.getElementById("app");const render = (messages) => {ReactDOM.render(<Provider store={store}><LanguageProvider messages={messages}><ConnectedRouter history={history}><Router history={history}><App /></Router></ConnectedRouter></LanguageProvider></Provider>,MOUNT_NODE);};if (module.hot) {// Hot reloadable React components and translation json files// modules.hot.accept does not accept dynamic dependencies,// have to be constants at compile-timemodule.hot.accept(["./i18n", "containers/App"], () => {ReactDOM.unmountComponentAtNode(MOUNT_NODE);render(translationMessages);});}// Chunked polyfill for browsers without Intl supportif (!window.Intl) {new Promise((resolve) => {resolve(import("intl"));}).then(() =>Promise.all([import("intl/locale-data/jsonp/en.js"),import("intl/locale-data/jsonp/de.js"),])) // eslint-disable-line prettier/prettier.then(() => render(translationMessages)).catch((err) => {throw err;});} else {render(translationMessages);}// Install ServiceWorker and AppCache in the end since// it's not most important operation and if main code fails,// we do not want it installedif (process.env.NODE_ENV === "production") {require("offline-plugin/runtime").install(); // eslint-disable-line global-require}
/**** containers/App/index.js** This component is the skeleton around the actual pages, and should only* contain code that should be seen on all pages. (e.g. navigation bar)*/import React, { useEffect, useMemo } from "react";import { Helmet } from "react-helmet";import styled from "styled-components";import { Link } from "react-router-dom";import { Switch, Route } from "react-router-dom";import history from "utils/history";import {HOC as HocConfigure,commonConstants,} from "react-boilerplate-redux-saga-hoc";import HomePage from "containers/HomePage/Loadable";import FeaturePage from "containers/FeaturePage/Loadable";import NotFoundPage from "containers/NotFoundPage/Loadable";import Header from "components/Header";import Footer from "components/Footer";import createReducer from "../../reducers";import GlobalStyle from "../../global-styles";const AppWrapper = styled.div``;const HOC = HocConfigure({handlers: [{ name: "NAME" }],createReducer,});const BASE_URL = "https://jsonplaceholder.typicode.com";const DEMO_GET_API = {url: `${BASE_URL}/posts`,method: "GET",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "status",errorMessageKey: "error",};/*Note: If you want to pass params to the url such as id,type etc.change `${BASE_URL}/posts` to ({ id }) => `${BASE_URL}/posts/${id}`*/const DEMO_POST_API = {url: ({ id }) => `${BASE_URL}/posts/${id}`,method: "POST",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "status",errorMessageKey: "error",};const DEMO_DELETE_API = {url: ({ id }) => `${BASE_URL}/posts/${id}`,method: "DELETE",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "status",errorMessageKey: "error",};const DEMO_PUT_API = {url: ({ id, type }) => `${BASE_URL}/posts/${id}/${type}`,method: "PUT",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "status",errorMessageKey: "error",};const AuthenticationHOC = HOC({initialState: {profile: {},},useHook: true,apiEndPoints: {DEMO_GET_API,DEMO_POST_API,DEMO_DELETE_API,DEMO_PUT_API,},name: "Auth",});function App(props) {return (<AppWrapper><HelmettitleTemplate="%s - React.js Boilerplate"defaultTitle="React.js Boilerplate"><meta name="description" content="A React.js Boilerplate application" /></Helmet><Header /><Switch><Route exact path="/" component={HomePage} /><Route path="/features" component={FeaturePage} /><Route path="" component={NotFoundPage} /></Switch><Footer /><GlobalStyle /></AppWrapper>);}export default AuthenticationHOC(App);
# Installing on React-Native
Note:Please make sure to install required dependencies.
npm install redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
If you are using yarn:
yarn add redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
/*** index.js*/import React from "react";import { AppRegistry } from "react-native";import { Provider } from "react-redux";import { store as configureStore } from "react-boilerplate-redux-saga-hoc";import App from "./App";import { name as appName } from "./app.json";const initialState = {};const store = configureStore(initialState);AppRegistry.registerComponent(appName, () => (props) => (<Provider store={store}><App {...props} /></Provider>));
/*** Sample React Native App* https://github.com/facebook/react-native** @format* @flow strict-local*/import { compose } from "redux";import React from "react";import {SafeAreaView,StyleSheet,ScrollView,View,Text,StatusBar,} from "react-native";import { HOC as HocConfigure } from "react-boilerplate-redux-saga-hoc";import {Header,LearnMoreLinks,Colors,DebugInstructions,ReloadInstructions,} from "react-native/Libraries/NewAppScreen";const HOC = HocConfigure({handlers: [{ name: "NAME" }],isReactBoilerplate: false,});const NewHoc = HOC({initialState: {profile: {},},dontReset: {TEST_API: {},TEST_SUB_API: {},},useHook: true,apiEndPoints: {TEST_API: {},TEST_SUB_API: {},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},constantReducer: ({ type, state }) => {if (type === "NAME")return {...state,name: "NAME",};return state;},name: "NAME2",});const AuthHoc = HOC({initialState: {profile: {},},dontReset: {TEST_API: {},},useHook: true,apiEndPoints: {TEST_API: {url: "https://jsonplaceholder.typicode.com/posts/",method: "GET",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "message",},TEST_SUB_API: {},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},constantReducer: ({ type, state }) => {if (type === "NAME")return {...state,name: "NAME",};return state;},name: "Auth",});const App = (props) => {console.log(props);React.useEffect(() => {const {Auth_hoc: {actions: { TEST_API_CALL },},} = props;TEST_API_CALL();}, []);return (<><StatusBar barStyle="dark-content" /></>);};export default compose(NewHoc, AuthHoc)(App);
# Installing on Next-js
Note:Please install redux-saga version 0.16.2.This package does not support latest version on redux-saga.Please make sure to install required dependencies.
npm install redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
If you are using yarn:
yarn add redux-saga@0.16.2 react-redux react-boilerplate-redux-saga-hoc
/* config.js */import { HOC as HocConfigure } from "react-boilerplate-redux-saga-hoc";const HOC = HocConfigure({ handlers: [], nextJS: true, useHook: true });const { saga: AuthSaga, reducer: AuthReducer, hoc: AuthenticationHOC } = HOC({initialState: {profile: {},},apiEndPoints: {TEST_API: {url: "https://jsonplaceholder.typicode.com/posts/",method: "GET",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "message",},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},name: "Auth",});const { saga: DashSaga, reducer: DashReducer, hoc: DashHOC } = HOC({initialState: {profile: {},},apiEndPoints: {TEST_API: {url: "https://jsonplaceholder.typicode.com/posts/",method: "GET",responseStatusCode: [900],responseStatusCodeKey: "code",responseDataKey: "data",responseMessageKey: "message",},REGISTER_API: {url: `users/user-signup/`,method: "POST",},},name: "Dash",});const Store = createStore({saga: [AuthSaga, DashSaga],reducer: [AuthReducer, DashReducer],});export { AuthenticationHOC, DashHOC, Store };
/* pages/_app.js*/import React from "react";import App from "next/app";import { Provider } from "react-redux";import { withRedux, withReduxSaga } from "react-boilerplate-redux-saga-hoc";import { Store } from "./config.js";function MyApp({ Component, pageProps, store }) {return (<Provider store={store}><Component {...pageProps} /></Provider>);}MyApp.getInitialProps = async (appContext) => {// calls page's `getInitialProps` and fills `appProps.pageProps`const appProps = await App.getInitialProps(appContext);return { ...appProps };};export default withRedux(Store)(withReduxSaga(MyApp));
/* _app.js *//* Hoc will use get initial props. please add this in _app.js inorder to use hoc in ssr */import App from "next/app";MyApp.getInitialProps = async (appContext) => {// calls page's `getInitialProps` and fills `appProps.pageProps`const appProps = await App.getInitialProps(appContext);return { ...appProps };};
/* pages/index.js */import Head from "next/head";import { compose } from "redux";import { toPromise } from "react-boilerplate-redux-saga-hoc";import { AuthenticationHOC, DashHOC } from "./config";function Home(props) {console.log(props);React.useEffect(() => {const {store,isServer,Auth_hoc: {actions: { TEST_API_CALL },},} = props;TEST_API_CALL();}, []);return (<div className="container"><Head><title>Create Next App</title><link rel="icon" href="/favicon.ico" /></Head><h1>create next app</h1></div>);}Home.getInitialProps = async (props) => {const { store, isServer } = props.ctx || props;const {Auth_hoc: {actions: { TEST_API_CALL, REGISTER_API_CALL },},Dash_hoc: {actions: { TEST_API_CALL: DashTest },},} = props;TEST_API_CALL(); // non-blocking call/* toPromise is mostly used for login api calls */const { status, error, reponse } = await toPromise(TEST_API_CALL); // blocking call - it will execute next line if promise is resolvedif (status === "SUCCESS")await toPromise(REGISTER_API_CALL, {request: {payload: {name: "test",password: test,},},});else if (status === "Error") console.log("Error");return {isServer,};};export default compose(AuthenticationHOC, DashHOC)(Home);
/* _app.js *//* add this in _app.js if you are using nextJs 9.3 or later */import App from "next/app";MyApp.getInitialProps = async (appContext) => {// calls page's `getInitialProps` and fills `appProps.pageProps`const appProps = await App.getInitialProps(appContext);return { ...appProps };};
# Getting regenerator runtime error
Note:If you are getting regenerator runtime error.Please make sure you have added babelrc file in your nextjs project.
npm install babel-preset-next --save-dev
or
yarn add babel-preset-next --dev
.babelrc
{"presets": ["next"// Add your babel presets here],"plugins": [// Add your babel plugins here]}
Next - Basic Concepts