Best Online Tutorials

SQL Tutorial

Free SQL Tutorial

SQL Interview Questions

SQL Practice Questions

SQL Tips & Tricks

SQL Errors

SQL Books

Angular Tutorial

Free Angular Tutorial

Angular Interview Questions

Angular Practice Questions

Angular Tips & Tricks

Angular Errors

Angular Books

Node.js Tutorial

Free Node.js Tutorial

Node.js Interview Questions

Node.js Practice Questions

Node.js Tips & Tricks

Node.js Errors

Node.js Books

React.js Tutorial

Free React.js Tutorial

React.js Interview Questions

React.js Practice Questions

React.js Tips & Tricks

React.js Errors

React.js Books

SSIS Tutorial

Free SSIS Tutorial

SSIS Interview Questions

SSIS Practice Questions

SSIS Tips & Tricks

SSIS Errors

SSIS Books

SEO Tutorial

Free SEO Tutorial

SEO Interview Questions

SEO Practice Questions

SEO Tips & Tricks

SEO Errors

SEO Books

Javascript Tutorial

Free Javascript Tutorial

Javascript Interview Questions

Javascript Practice Questions

Javascript Tips & Tricks

Javascript Errors

Javascript Books

MongoDB Tutorial

Free MongoDB Tutorial

MongoDB Interview Questions

MongoDB Practice Questions

MongoDB Tips & Tricks

MongoDB Errors

MongoDB Books

Next.js Tutorial

Free Next.js Tutorial

Next.js Interview Questions

Next.js Practice Questions

Next.js Tips & Tricks

Next.js Errors

Next.js Books

Next.js with redux 

Prashant Surya  |   Jun 22, 2020  |  Views: 270
pictures

Description:

Next.js is a React Framework used to create SPA application using React. While making a react Application sometimes we need SEO to be enabled in our application. 

To make a SEO friendly application we use Next.js which helps in SSR (Server-Side Rendering) and SSG (Static Site Generation).

We can make either SSG application using Next.js or SSR application.

Hybrid of using both SSR & SSG is also possible in Next.js.

Now the next question comes in our mind is that how we use Redux framework with the Next.js framework.For that one should have basic ideas of JavaScript and React.js before start using Next.js and Redux.


What topics we cover in this article:

  • Setup of Next.js Project
  • Integration of Redux Framework
  • With a demo application
  • Deployment of application

1. Setup of Next.js Project:


Step 1:

Next.js require node.js environment , so you need to install Node.js if not installed in your development environment.

Node.js 10.13 or more is required to be installed.



Step 2:

Now use the "create-next-app" which bootstraps a Next.js app for you

npm Install create-next-app

After installing the "create-next-app" 

$ npx create-next-app

It will ask for the project name, lets suppose we use "dc-app"..

cd dc-app
dc-app> npm run dev


2. Integration of Redux Framework:


I assume that you have the basic knowledge about the Redux Framework while reading this article, if not you can learn from Redux tutorials available on Redux website.

I am giving some overview before starting the implementation.

Redux is a framework which helps to manage state of an application. If someone changes the state of the application, the change will be reflected to whole application.

In simple word, we create a state and all the application use the same state, whenever there is need to be changed we take out the state and changes are made on it and 

then set with the next updated state.


For that we need to understand 

Action : UI triggers Action
Dispatch : Action Dispatches "Action Type" & "payloads" to reducers
Reducer : According the "Action Type" Reducer decides what to do, and payload offer the arguments required while doing the changes, Reducer pulls out the state from the 

Store and make the changes and again push into it with a new state without overwriting the old state.

Store: It keeps the data with modified states, UI uses the last updated state.



Step 1: Create Store.tsx


import { createStore, applyMiddleware, compose } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import appReducer from '../reducers';
export const InitialStateData = {
  lastUpdate: 0,
  data:null,
  count: 0
}
const enhancer = compose(
  composeWithDevTools(applyMiddleware(thunkMiddleware))
)
export function initializeStore(initialState = InitialStateData) {
  const store = createStore(appReducer, initialState, enhancer)
  return store;
}

- It will return a new initialized store (a new state of data) for you.

- We are using Redux-thunk to manage async calls as middleware, so we are adding the middleware as thunkMiddleware


Step 2: 

Next.js offers three methods for playing with the props

While in Next.js a page is rendered two times, so a server side request and a client side request both arises when a page is called.

We need to set props at server side request with a new state at each request and share the same state with the client request, so to manage the same state while rendering.

getInitialProps - before Next.js 9.3.0 it was used for both server side as well as for client side
getServerSideProps - from Next.js 9.3.0, we use getServerSideProps for getting/setting props in server side
getStaticProps - need for static pages



Application structure:

root/
   actions/
actionTypes.tsx
userActions.tsx
   asyncActions/
userAsyncActions.tsx
   store.tsx
   lib/with-redux-store.tsx
   pages/
_app.tsx
user.tsx
   Reducer/
index.tsx
userReducer

Now create a file named with-redux-store.tsx which will do the following thing for you:

- It will create a new state of store and set it with each page request by using getInitialProps


import React from 'react'
import { initializeStore, exampleInitialState } from '../domain/store'
const isServer = typeof window === 'undefined'
const __NEXT_REDUX_STORE__ = '__NEXT_REDUX_STORE__'
function getOrCreateStore(initialState) {
  // Always make a new store if server, otherwise state is shared between requests
  if (isServer) {
    return initializeStore(initialState)
  }
  // Store in global variable if client
  if (!window[__NEXT_REDUX_STORE__]) {
    window[__NEXT_REDUX_STORE__] = initializeStore(initialState)
  }
  return window[__NEXT_REDUX_STORE__]
}
export type Store = ReturnType<typeof getOrCreateStore>
type Props = { reduxStore: Store }
const withReduxStore = (Component: React.ComponentClass<Props>) => {
  return class Redux extends React.Component<Props> {
    private reduxStore
    static async getInitialProps (appContext) {
      const reduxStore = getOrCreateStore(exampleInitialState)
      // Provide the store to getInitialProps of pages
      appContext.ctx.reduxStore = reduxStore
      let appProps = {}
      if ((Component as any).getInitialProps) {
        appProps = await (Component as any).getInitialProps(appContext)
      }
      return {
        ...appProps,
        initialReduxState: reduxStore.getState()
      }
    }
    constructor(props) {
      super(props)
      this.reduxStore = getOrCreateStore(props.initialReduxState)
    }
    render() {
      return (
        <Component {...this.props} reduxStore={this.reduxStore} />
      )
    }
  }
}
export default withReduxStore
export const mapDispatchToProps = dispatch => ({ dispatch })
export type Dispatchable<P> = P & ReturnType<typeof mapDispatchToProps>
Step 3: update the pages/_app.tsx

import * as React from 'react'
import { Provider } from 'react-redux'
import App from 'next/app'
import withReduxStore, { Store } from '../lib/with-redux-store';
interface Props { reduxStore: Store }
export default withReduxStore(
    class extends App<Props> {
        async getInitialProps({ Component, ctx, reduxStore }) {
            const server = !!ctx.req
            const store = reduxStore;
            const state = store.getState()
            const out = { state, server } as any
            if (Component.getInitialProps) {
                return {
                    ...out,
                    pageProps: {
                        ...await Component.getInitialProps(ctx)
                    }
                }
            }
            return out
        }
        render() {
            const { props } = this as any
            const { Component, pageProps, reduxStore } = props;
            return (
                 <Provider store={reduxStore}>
                       <Component {...pageProps} />
                 </Provider>
            )
        }
    }
)
Step 4: Create a page user.tsx

import { connect } from 'react-redux'
import React from 'react';
import { Dispatchable } from '../lib/with-redux-store';
import { getUsersList,getUserById,updateUser,deleteUser,addNewUser } from '../asyncActions/usersAsyncActions.tsx'
interface Props {
   getUsersList, getUserById, updateUser, deleteUser, addNewUser, usersList, userDetail
}
type MyState = { input: string };
class User extends React.Component<Dispatchable<Props>, MyState> {
    handleChange = (e) => {
        this.setState({ input: e.target.value });
    }
    componentDidMount() {
       
    }
    render() {
        const { data } = this.props;
        return (
            <div>
{data.name}
            </div>
        )
    }
}
const mapStateToProps = (state) => {
    let obj = {
        usersList: state.users.data,
userDetail:state.user.data
    }
    return obj;
}
const mapDispatchToProps = {
    getUsersList,getUserById,updateUser,deleteUser,addNewUser
}
export default connect(mapStateToProps, mapDispatchToProps)(User)
Step 5: create actionTypes in actions/actionTypes.tsx:

export const GET_USER_LIST_STARTED = 'GET_USER_LIST_STARTED';
export const GET_USER_LIST_SUCCESS = 'GET_USER_LIST_SUCCESS';
export const GET_USER_LIST_FAILURE = 'GET_USER_LIST_FAILURE';
export const GET_USER_DETAIL_STARTED = 'GET_USER_DETAIL_STARTED';
export const GET_USER_DETAIL_SUCCESS = 'GET_USER_DETAIL_SUCCESS';
export const GET_USER_DETAIL_FAILURE = 'GET_USER_DETAIL_FAILURE';



Step 6: Create action/userActions.tsx:

import {
    GET_USER_LIST_STARTED, GET_USER_LIST_SUCCESS, GET_USER_LIST_FAILURE,
    GET_USER_DETAIL_STARTED, GET_USER_DETAIL_SUCCESS, GET_USER_DETAIL_FAILURE
  } from "./actionTypes";
  
  // to get the list of USERs - started
  export const getUserListStarted = () => {
    return {
      type: GET_USER_LIST_STARTED
    }
  }
  
  // to get the list of USERs - success
  export const getUserListSuccess = (data,page) => {
    return {
      type: GET_USER_LIST_SUCCESS,
      payload: {
        data,page
      }
    }
  }
  
  // to get the list of USERs - failure
  export const getUserListFailure = error => {
    return {
      type: GET_USER_LIST_FAILURE,
      payload: {
        error
      }
    }
  }
  //--------------------------------DETAILS-----------------------------
   // to get the DETAIL of USER - started
   export const getUserDetailStarted = () => {
    return {
      type: GET_USER_DETAIL_STARTED
    }
  }
  
  // to get the DETAIL of USER - success
  export const getUserDetailSuccess = (data) => {
    return {
      type: GET_USER_DETAIL_SUCCESS,
      payload: {
        data        
      }
    }
  }
  
  // to get the DETAIL of USER - failure
  export const getUserDetailFailure = error => {
    return {
      type: GET_USER_DETAIL_FAILURE,
      payload: {
        error
      }
    }
  }



Step 7: Create Reducers/UserReducer.tsx

import {
  GET_USER_LIST_STARTED, GET_USER_LIST_SUCCESS, GET_USER_LIST_FAILURE,
} from "../actions/actionTypes";

export type UserState = {
  data: any,
  loading: boolean,
  count: number,
  error: any,
  currentPage: number,
  keyword: string
}
// define initial state of USER
const initialState = {
  data: {},
  loading: false,
  count: 0,
  error: null,
  keyword: '',
  currentPage: 1
}

export default function common(state:any = initialState, action:any) {
  switch (action.type) {
    case GET_USER_LIST_STARTED:
      return {
        ...state,
        loading: true
      }
    case GET_USER_LIST_SUCCESS:
      const { data, page } = action.payload;

      let recent = state.recent || [];
      if (page == 1) {
        recent = data;
      }
      const obj = {}
      obj[page] = data;
      return {
        ...state,
        data: { ...state.data, ...obj },
        loading: false,
        currentPage: page,
        recent: recent
      }
    case GET_USER_LIST_FAILURE:
      const { error } = action.payload;
      return {
        ...state,
        error
      }
    default:
      return state
  }
}


Step 8: Combine all reducers in reducers/index.tsx

import { combineReducers } from 'redux';
import user from './userReducer';
// to combine all reducers together
const appReducer = combineReducers({
   user,...
});
export default appReducer;


Step: 9 Create asyncActions/userAsyncActions.tsx


import {
  getUserListStarted, getUserListSuccess, getUserListFailure,
  getUserDetailStarted, getUserDetailSuccess, getUserDetailFailure
} from "../actions/UserActions";

export const getUsersList = (page = 1, keyword = '') => async dispatch => {
  let pg = page - 1;
  dispatch(getUserListStarted());
  try {
    const res = await fetch(`www.xyz.com/api/USERs/list?limit=10&page=${pg}&keyword=${keyword}`);
    const data = await res.json();
    dispatch(getUserListSuccess(data, page));
  } catch (err) {
    dispatch(getUserListFailure(err.message));
  }
}

export const getUserDetail = (slug) => async dispatch => {
  dispatch(getUserDetailStarted());
  try {
    const res = await fetch(`www.xyz.com/api/USERs/list/${slug}`);
    const data = await res.json();
    dispatch(getUserDetailSuccess(data));
  } catch (err) {
    dispatch(getUserDetailFailure(err.message));
  }
}


Step 10: Update pages/user.tsx

import { connect } from 'react-redux'
import React from 'react';
import { Dispatchable } from '../lib/with-redux-store';
import { getUsersList,getUserById,updateUser,deleteUser,addNewUser } from '../asyncActions/usersAsyncActions.tsx'
interface Props {
   getUsersList, usersList
}
type MyState = { input: string };
class User extends React.Component<Dispatchable<Props>, MyState> {
    handleChange = (e) => {
        this.setState({ input: e.target.value });
    }
    componentDidMount() {
       
    }
  static async getInitialProps(obj) {
    if (obj.req) {
      await obj.reduxStore.dispatch(getUsersList());
      return {
        server: true,
      }
    }
    else {
      return {
        server: false
      }
    }
  }
    render() {
        const { data } = this.props;
        return (
            <div>
{usersList && usersList.map((x,i)=>
   <p key={i}>{x.name}</p>
)}

            </div>
        )
    }
}
const mapStateToProps = (state) => {
    let obj = {
        usersList: state.users.data
    }
    return obj;
}
const mapDispatchToProps = {
    getUsersList
}
export default connect(mapStateToProps, mapDispatchToProps)(User)
After adding and updating all files, lets run our application

npm run dev

You can check your application at http://localhost:3000 in your browser. You need to install all misisng redux packages if not installed in application.


Deployment of Next.js-React-Redux Application 


Step 1: Add your apllication to git repo
Step 2: Connect your hosting environment terminal
Step 3: git clone "GIt_APP_URL"
Step 4: cd app_name
Step 5: npm install
step 6: npm run build
step 7: npm run start


 





 





Comments:
Content Contributor
Prashant Surya

Prashant Surya

Software developer at Uniserve Data Technologies Pvt. Ltd.  |   Noida, Uttar Pradesh, India

I am a software developer, freelancer and trainer working on technologies likes. MEAN stack, MERN Stack, ASP.NET full stack , SQL, JavaScript, jQuery, HTML, CSS, SEO, responsive UI/UX designing... having 7 years of experience in development in multiple domains like, eCommerce, capital markets, education, real estate...


Want to sell your software ?-

If you want to sell your readymade software to the genuine clients or businessman, list your software with details and demo links.

  • Sell ERP
  • Sell Website Clones
  • Sell App Clones
  • Sell Readymade Portals
  • Sell Readymade Websites
  • Sell Mobile Apps
  • Sell Window Apps

Clients will find it using our advanced search filter and will contact you directly.

No any charge for the product lsiting.

Do you own a Company ?+

Property.sale

Buy or Sell Commercial Property+

Are you a freelancer ?+

Looking for a job ?+

Are you a Service Provider ?+

Are you a blogger ?+

Do you own an IT Institute ?+


Property.sale