React JS, Redux with Express Backend - Part II

Creating a React application with Express JS backend

Posted on December 21, 2017

In the previous post, we set the premises for React-Redux application. Let's discuss creating a job dashboard. We'll concentrate on the front-end in this post.

The front-end application uses React and Redux and does the following.

  • Display a list of job postings from the server
  • Create a new job posting
  • Delete job posting
  • View job posting details
We'll create an Express JS application that talks to an SQLite3 database. The jobs data is stored in SQLite3. We'll get to this part quickly. For now, let's assume that ExpressJS or the server application is running in http://localhost:3001. Our front-end application will perform calls to the server application.

create-react-app

Let's create a React application, jobs-reactjs using the NodeJS utility, create-react-app. As we're using Redux framework, let's install the redux and react-redux modules. Shown below is the package.json file.

					
	{
	  "name": "jobs-reactjs",
	  "version": "0.1.0",
	  "private": true,
	  "proxy": "http://localhost:3001", // ??
	  "dependencies": {
	    "axios": "^0.17.1", // ??
	    "express": "^4.16.2",
	    "react": "^16.2.0",
	    "react-dom": "^16.2.0",
	    "react-modal": "^3.1.7",
	    "react-redux": "^5.0.6",
	    "react-scripts": "1.0.17",
	    "redux": "^3.7.2"
	  },
	  "scripts": {
	    "start": "react-scripts start",
	    "build": "react-scripts build",
	    "test": "react-scripts test --env=jsdom",
	    "eject": "react-scripts eject"
	  }
	}
						
					
				

The proxy property in package.json, is the bridge to the server. All AJAX calls we make to the server application will be routed to http://localhost:3001 configured in the proxy. This is strictly for development purpose only.

We'll use the axios library for AJAX requests from the browser. Axios is a promise-based library. You can also try out other libraries like fetch, request etc.

Starting Point: Store and Reducers

The fundamental job of Redux is maintaining the state of the application and the code to manipulate the state separately. The Store instance maintains the state, which is nothing but a JSON object. The Reducers maintain the behavior or operations. And we just wire the store with the entire application using the <Provider> element. We have a store and jobsReducers wired up with the <Provider> as shown below.


	...
	import jobsReducers from 'jobs/JobsReducers'
	import {createStore} from 'redux'

	let store= createStore(jobsReducers)

	ReactDOM.render(
	(<Provider store={store}>
		<App/>
	</Provider>), 
	document.getElementById('root'));
		

The jobsReducers is a mega-sized switch-case construct that has the behaviors for various Job operations. Given below is the code for creating and loading operations. The reducer operations return a state. One of the points to notice here is, the state is immutable. So every operation returns a new state. We can create multiple reducers and combine them, as well. In our case, we just have one reducer.

			
//...
const jobsReducers = (state=initialState,action) => {

  switch (action.type) {
    //...  
    case "SHOW_JOB_DETAILS":
      let jobDetailsToShow = state.jobs.find( job => job.id === action.payload.jobid )
      return { jobs: state.jobs, jobDetailsToShow, jobDetailsShown: true }	
    case "LOAD_JOBS_SUCCESS":
      state.jobs = action.payload.jobs
      return {jobs: action.payload.jobs, addJobShown: false} 
    default:
      return state
  }
}
//...
				
		

The reducers accept the state and action instance as arguments. Based on the type of action, we perform the neccessary job and construct a state. In the code above, the SHOW_JOB_DETAILS action, picks up the job postings from the collection of jobs and returns it. The LOAD_JOBS_SUCCESS action returns the collection of jobs.

React Components to list the jobs

We have two react components JobsList and JobsItem to display the components. The JobsList, when loaded, sends a request to the server, and fetches the jobs and displays them. Each job posting is converted to an instance of JobsItem component.


class JobsList extends Component{
	
    componentDidMount(){
       this.props.loadJobs()
    }
    populateJobs(){
        let {jobs} = this.props
        let jobListItems = []
        jobs.forEach(job => {
           let item = 
           jobListItems.push(item)	
        })
        return jobListItems
    }
	
    render(){
        return (<div style={{display: this.props.addJobShown ? "none":"block"}}>
                  <h2>Jobs List</h2>
                  {
                    this.props.jobs.length === 0 ?
                    `No jobs found` : 
                    (<ul className='joblist'>
                       {this.populateJobs()}	
                       </ul>)
                  }
                </div>)
    }
}					
				

As you can see, the component calls this.props.loadJobs() from componentDidMount(). The populateJobs() method called from render() iterates this.props.jobs and renders each job as an instance of JobsItem.
But where is this loadJobs() method defined?.
But where is this this.props.jobs data defined?.

The Redux magic comes to play.