(Build your site with react redux)

Build for support large application development,developer can easily develop website, management system by this starter kit. This is not good starter kit who are looking for CMS(content management system). This Starter kit is good for who want to learn and develop with react redux from scratch.

Github Link: https://github.com/tariqulislam/react-redux-web-starter

Table of Contents

Project Structure

|--| build
|--| config
|--| public (static file to load in this starter kit)
|----| favicon.ico
|----| index.html
|----| mainfest.json
|--| script
|----| build.js
|----| start.js
|----| test.js
|--| src
|----| asset
|------| [cssfile.scss]
|------| [Static Image Files]
|----| component
|------| [Global Component Folder]
|------| [Global Component(.js)]
|----| container
|------| [Global Smart Component Folder]
|------| [Global Smart File(.js)]
|----| layout [Main Layouts of the projects]
|----| core
|------| initializeStore.js (Initilize the main store for redux)
|------| rootReducer.js (Main reducer class for root)
|------| withReducer.js (For Lazy loading the redux store)
|----| router[Control all the routes of app]
|------| withAuthRoute.js
|------| withoutAuthRoute.js
|----| reducers[Configure the router]
|------| [Global Reducer Folder for Redux]
|------| [Global Reducer File(.js)]
|----| routes
|------| [Module Folder]
|--------| asset
|----------| [modulecssfile.scss]
|----------| [Static Image Files]
|--------| component
|----------| [Module Component Folder]
|----------| [Module Component File(.js)]
|--------| container
|----------| [Module smart component Folder]
|----------| [Module smart component File (.js)]
|--------| reducer
|----------| [Module Reducer File for Redux]
|--------| index.js (connect all the container and component for module wise redux store Lazy loading)
|------| routeSplit.js (Appling the code spliting to Each Module)
|----| shared
|-------| [Global Shared Function File]
|----| test
|-------| [React Test file(.test.js)]
|--| .eslintrc
|--| .gitignore
|--| package-lock.json
|--| package.json
|--| postcss.config.js

Special Notes

1. Lazy loading for Redux Store
2. Module wise Code Spliting

For Lazy loading of Redux Store, I have introduced a function called withReducer() which will load the redux on demand at runtime. for spliting the redux store we can just add the code below at every module at index.js:

export default withReducer('homeReducer'/** key for reducer to split **/, 
homeReducer/** reducer name for module **/)
(HomeContainer/** container or samrt component which create connection between redux and component)

For Module wise Code Spliting, I have introduced React Loadable package, which will split the code at production and runtime also

Loadable({
loader: () => import('./About' /** component name or module which will be split by webpack*/),
loading: <LoadingComponent />, /** custom loading component which will be shows when component will be delay to load */
delay: 300 /** Milisecond to wait for component to load */
})

Installation and Configure

  1. Then run the command for:
  2. For npm : npm run install
  3. For Yarn run : yarn install
  4. Application will run at local development server with port

New Module Development

1. to go to  -> ```routes``` folder.  
2. create other necessary folders with ```index.js``` file.
Example:
```
|----| routes
|------| Contact
|--------| asset
|----------| contact.scss
|--------| component
|----------| Contact.js
|--------| container
|----------| ContactContainer.js
|--------| reducer
|----------| ContactReducer.js
|--------| index.js
```

Create the Component for design the page named Contact.js:

Example:

import React from 'react'export const Contact = (props) => {
return (
<div> This is contact page </div>
)
}
export default Contact

Redux Implementation for New Module

Add the redux store code to ContactReducer.js:

Create the action constraint

Example:

export const GET_CONTACT_INFO = 'GET_CONTACT_INFO'
export const SET_CONTACT_INFO = 'SET_CONTACT_INFO'

Create the initial state for redux store

const initialState = {
contactTitle: null,
contactDetails: null
}

Create the actions for handle the payload and reducer

Example:

export function getContactInfo () {
return {
type: GET_CONTACT_INFO,
payload: {}
}
}
export function setContactInfo (data) {
return {
type: SET_CONTACT_INFO,
payload: {data}
}
}

Create object structure which has defination for handling reducer

Example:

const CONTACT_ACTION_HANDLER = {
[GET_CONTACT_INFO]: (state, action) => {
return ({...state, contactTitle: null, contactDetails: null})
},
[SET_CONTACT_INFO]: (state, action) => {
return ({...state, contactTitle: action.payload.data.contactTitle, contactDetails: action.payload.data.contactDetails})
}
}

Conditional statement for handle the contact reducer

Example:

export default function contactReducer (state = initialState, action) {
const handler = CONTACT_ACTION_HANDLER[action.type]
return handler? handler(state, action): state
}

Add the code to smart component ContactContainer.js for connect the redux to react component:

import main component (Contact.js) and connect function which will create connection between React component and redux reducer, And then import the ContactReducer.js reducer to smart component ContactContainer.js

import {connect}  from 'react-redux'
import {
getContactInfo,
setContactInfo
} from '../reducer/ContactReducer'
import Contact from '../component/Contact'

Create function which will dispatch the reducer

const loadRenderContactInfo = (dispatch) => {
dispatch(getContactInfo())
dispatch(setContactInfo({
contactTitle: "This is new contact title",
contactDetails: "This is new contact details"
}))
}

Create the mapStateToProps() (default function for redux) which will maintain all the state for the Contact.js component.

const mapStateToProps = (state) => ({
contactTitle: state.contactReducer.contactTitle,
contactDetails: state.contactReducer.contactDetails
})

Create the mapActionCreators() (default function for redux) which will maintain all the functions from redux and those function are related to react component Contact.js

const mapActionCreator = (dispatch) => ({
renderContactInfo: loadRenderContactInfo(dispatch)
})

Connect the redux with react component Contact.js

export default connect(
mapStateToProps,
mapActionCreator
)(Contact)

Apply lazy loading to (Contact -> index.js) file for Split Redux store for Contact module

import ContactContainer from './container/ContactContainer'
import contactReducer from './reducer/ContactReducer'
import {withReducer} from 'core/withReducer'
export default withReducer('contactReducer', contactReducer)(ContactContainer)

Add the code spliting functionality for Contact module by appling react loadable to ( routes -> routeSplit.js) file

const Contact = Loadable({
loader: () => import('./Contact'),
loading: Loading,
delay: delay
})
export { Home, About, Contact }

To Add the Contact module at Menu Bar, we should add following below object at (shared -> AppHelper.js -> getNavigationItem -> TopNav)

For the Routing purpose of Contact module at the following code below (router -> WithAuthRoute.js)

  1. WithAuthRoute.js : Using the Route after authentication and authorization
  2. WithoutAuthRoute.js : Using Before authentication and authorization

<Route exact path="/contact" component={Contact} />

Change the Contact.js page with following below code

import React from 'react'export const Contact = (props) => {
return (
<div>
<h1>{props.contactTitle}</h1>
<p>{props.contactDetails}</p>
</div>
)
}
export default Contact

Handle Ajax Request

Following code gose to ContactReducer.js file:

Import the axios package in sample:

import axios from 'axios'
import RequestHeaderHelper from 'shared/RequestHeaderHelper'

Add the Action constraint for handling the ajax request

export const GET_POST_INFO = 'GET_POST_INFO'
export const SET_POST_INFO = 'SET_POST_INFO'

Add the Actions for handling the ajax request

export function getPostInfo () {
return {
type: GET_POST_INFO,
payload: {}
}
}
export function setPostInfo (data) {
return {
type: SET_POST_INFO,
payload: {data}
}
}

Create the function which will get the data from api by using axios

export const getPostInfoFromApi = (data) => {
const url = `https://jsonplaceholder.typicode.com/comments?postId=${data.id}`
const request = axios.get(url, RequestHeaderHelper.jsonHeaderWithAuth())
return {type: 'GET_POST_INFO', payload: request}
}

Add the reducer control flow to handle redux store change

[GET_POST_INFO]: (state, action) => {
return ({...state, posts: null })
},
[SET_POST_INFO]: (state, action) => {
return ({...state, posts: action.payload.data })
}

Add the function to dispatch getPostInfoFromApi() function to smart component ContactContainer.js

const loadGetPostsInfo = (data,dispatch) => {
dispatch(getPostInfoFromApi(data))
.then(resonse => {
dispatch(setPostInfo(resonse.payload.data))
})
}

Add state posts to mapStateToProps() function passing the state from redux to react component

const mapStateToProps = (state) => ({
contactTitle: state.contactReducer.contactTitle,
contactDetails: state.contactReducer.contactDetails,
`posts: state.contactReducer.posts`
})

For getPostsInfo function accessible to react component we can add that function to mapActionCreators() at ContactContainer.js file

const mapActionCreator = (dispatch) => ({
renderContactInfo: loadRenderContactInfo(dispatch),
`getPostsInfo: (data) => loadGetPostsInfo(data,dispatch)`
})

Change the code of react component Contact.js for rendering the data consume from api

import React from 'react'
import map from 'lodash/map'
class Contact extends React.Component {

componentDidMount() {
const {renderContactInfo, getPostsInfo} = this.props
renderContactInfo()
getPostsInfo({id: 1})
}
render() {
const {posts, contactTitle, contactDetails} = this.props
console.log(this.props)
return (
<div>
<h1>{contactTitle}</h1>
<p>{contactDetails}</p>
<ul>
{
map(posts, post =>
<li>{post.name}</li>
)
}
</ul>
</div>
)
}
}
export default Contact

Tariqul Islam have 9+ years of software development experience. He knows Python, Node Js and Java, C# , PHP.