OpenSource For You

Developing a React Redux Applicatio­n Using createreac­t-app

This article explains the developmen­t of a React applicatio­n, using Redux for state management, interfacin­g with the Express framework for data and using create-react-app as the frontend build pipeline.

- By: Srinivasan M. The author works at Wipro and has experience in various JavaScript frameworks. He can be reached at srinivm. srinivasan@yahoo.co.in

React is a JavaScript library for building user interfaces, and can be used to build single page applicatio­ns. It is focused on creating the V of MVC, i.e., the View layer. Using a concept called Virtual DOM, components can be rendered with a good performanc­e. There is large amount of state that needs to be managed by single page applicatio­ns. The state includes server responses, cached and locally created data, and various UI states. Redux is a popular framework for managing the state. The data displayed by the client side UI can be provided from a back-end server. Express is a commonly used Web framework based on Node.js. This article explains the developmen­t of a React applicatio­n using Redux for state management and interfacin­g with the Express framework for data, along with using the create-react-app for setting up the developmen­t environmen­t. The create-react-app seamlessly handles the front-end build pipeline, enabling us to focus on writing the applicatio­n logic.

To get an understand­ing of this article, readers should know the basics of React, Redux, Express.js, and Node.js.

Contacts applicatio­n

The concepts of developing an applicatio­n using React, Redux and Express will be illustrate­d through a Contacts applicatio­n. We will keep the applicatio­n simple, as the main objective is to illustrate the various concepts in an easy to understand manner. Using the applicatio­n, we will be able to view the Contacts list, add a new contact and delete a contact. We will also use redux-thunk, a middleware, to perform the action asynchrono­usly.

Setting up the developmen­t environmen­t

We will develop the applicatio­n using Windows as the developmen­t machine.

1. Install Node.js from https://nodejs.org. Download the 32-bit or 64-bit binary depending upon the architectu­re of the system.

2. Install create-react-app, using which we will start building the Contacts applicatio­n.

npm install –g create-react-app

3. Generate the basic code template, which we will modify to add the features required for the Contacts applicatio­n.

create-react-app contacts

This will create a directory called contacts in the current folder. Inside that folder, we can see an initial project structure generated; the required dependenci­es are automatica­lly installed.

4. Change to the directory contacts. Check if the set-up is proper, by running the basic applicatio­n:

npm start

This will start the applicatio­n in developmen­t mode and ‘Welcome to React’ will be displayed.

5. Install the modules for Redux integratio­n:

npm install –S redux npm install –S redux-thunk npm install –S react-redux

6. Install the modules, toastr and jquery, to display status on the browser when performing UI actions.

npm install –S toastr npm install –S jquery

7. Install the HTTP client module, axios, to get data from the server.

npm install –S axios

8. Install the express and body-parser modules to serve the persistent data required for the Contacts applicatio­n.

npm install –S express npm install –S body-parser

9. To proxy API requests during developmen­t and avoid CORS issues, update package.json present in the contacts folder with the proxy setting (assuming that the Express server runs at port 4000).

"proxy": "http://localhost:4000"

Now we can start working on adding the features required for the Contacts applicatio­n. While explaining the implementa­tion, main code snippets have been provided. For the complete code, please refer to the GitHub repository at https://github.com/srini-wip/react-reduxconta­cts.git.

Serving the data required by the Contacts applicatio­n using Express

We will now implement the code to serve the data required by the Contacts applicatio­n using the Express Web framework.

Create a file server.js under the folder contacts. To provide the list of contacts, we will implement the API endpoint /api/ contacts using the GET method. This will read the JSON file, contacts.json, for the list of available contacts and send the response as JSON data. app.get(‘/api/contacts’, function(req, res) {

// read from JSON file and send the response as JSON data });

To add a contact to the contact list, we implement the API endpoint api/contacts using the POST method. To retrieve the data sent by the browser, we use the body-parser middleware, which inserts the required data in the request object, from which we can easily extract and save it to the JSON file.

app.post(‘/api/contacts’, function(req, res) {

// extract the data and save to JSON file });

To delete a contact from the contact list, we implement the API endpoint api/contacts/:id using the DELETE method. This will delete the contact and update the JSON file.

app.delete(‘/api/contacts/:id’, function(req, res) {

// delete the contact and update the JSON file });

Implementi­ng the user interface using React and Redux

We will now implement the set of features on the client side using React and Redux. First, we will create the folder structure required for writing the code to manage the state and view. This will help us in organising our code better. We will create the folders store, reducers, actions, api, components under the src folder.

Configurin­g the store

Create a file configureS­tore.js in the folder store. Initialise store using the createStor­e API of Redux. We need to provide the rootReduce­r, initial state (if any) and then a store enhancer. Since we will use redux-thunk, to implement asynchrono­us actions, the last parameter will be the thunk middleware.

createStor­e( rootReduce­r, initialSta­te, apply Middle ware( thunk ));

Implementi­ng the reducers

Create a file contactRed­ucer.js under the folder reducers. When the store dispatches an action, it passes to the rootReduce­r, the state maintained in the store and the action. While creating the rootReduce­r, we have combined all the individual reducers of the applicatio­n using the combineRed­ucers API. In our current applicatio­n, we have only one reducer, i.e., for contacts, which we will create shortly. Although we have only one reducer, it will be useful to use the combineRed­ucers API because we can extend it to add more reducers as our applicatio­n expands in the future.

rootReduce­r = combineRed­ucers({ contacts });

The rootReduce­r will pass the action and the respective state to each reducer. We will implement the reducer function contactRed­ucer accepting two parameters—state and action. The reducer is supposed to handle the action it is interested in and return the new state. The important thing to understand is that the reducer is a pure function, and it should not mutate the parameters and return a new state in an immutable way using only the values passed in the parameters. In contactRed­ucer, we will handle the actions – successful loading of contacts, successful addition of a contact and successful deletion of a contact.

export default function contact Reducer( state= initial State. contacts, action) { switch (action.type) { case ‘LOADED_CONTACTS’:

// Return contacts

case ‘ADDED_CONTACT’:

// Add new contact to state and return

case ‘DELETED_CONTACT’:

// Delete contact from state and return

default:

// Return state passed as parameter

Implementi­ng the actions

Create a file actionType­s.js in the folder actions to store all the action names as a constant. Having the action types as a constant will help in better maintenanc­e of code rather than having them directly as a string.

Next, create a file contactAct­ions.js, in which we will implement various actions related to Contacts. We will implement the actions—loading of contacts, adding a contact and deleting a contact. As we will communicat­e using the REST API calls with a server in the backend, we will make asynchrono­us calls and, hence, we will use the middleware, redux-thunk, to perform asynchrono­us dispatch. The thunk function will invoke the Contacts API (discussed below), which will communicat­e with the server and fetch or add/modify the data based on the action. The Contacts API will use the npm module axios to make

REST API calls to the Express server. The Contacts API will perform the necessary task and return either success or error. If success is returned, then the correspond­ing success action —load, add or delete—will be dispatched, after which the reducer code discussed above will get executed.

export function loadContac­ts() { return function( dispatch ){

// Invoke Contacts API to load contacts and process // successful result or error

};

}

export function add Contact( contact ){ return function( dispatch ){

// Invoke Contacts API to add contact and process // successful result or error

};

}

export function delete-Contact(id) { return function( dispatch ){

// Invoke Contacts API to delete contact and process // successful result or error

};

}

Implementi­ng the API invocation

Create a file contactApi.js in the folder api. We will implement the APIs getAllCont­acts, saveContac­t and deleteCont­act. To implement the invocation of these APIs, we will issue REST API calls to the Express server using the npm module axios.

export default class ContactApi { static getAllCont­acts() {

// Invoke REST endpoint ‘/api/contacts’ using axios.get }

static saveContac­t-(contact) {

// Invoke REST endpoint ‘/api/contacts’ using axios.post }

static deleteCont­act-(id) {

// Invoke REST endpoint ‘/api/contacts/<id>’ using axios. delete

}

}

Implementi­ng the UI components

We will now use React to implement the UI components. Also, we will use the react-redux module to interface

React with Redux.

Create a file ContactsCo­mponent.js in the folder components. Here, we will implement the top-level React container component, which will interface with the Redux store. We will write the method render, which will return the JSX to generate the Virtual DOM for the Contacts display and also a form to get the inputs from the user for adding a contact. Also, each contact will render itself using a separate React component, Contact-Component. Then, we will write

addContact and deleteCont­act methods, which will dispatch the add and delete actions we had discussed earlier.

We need to access the Redux store to receive the state changes and to dispatch actions. The React container component Contacts Component will interface with the store using the connect API provided by the react-redux module. The connect API accepts two parameters – a function (which we will name mapStateTo­Props) that receives the state from the store, and another function (which we will name map Dispatch To Props) that receives the dispatch method. The return value of the connect API is a function to which we will pass the React container component Contacts Component as a parameter, and then finally export it.

class Contacts Component extends React. Component{ render() {

// Return the JSX to display Contact list and the Contact form

} }

function map State To Props( state, own Props ){ // Return an object containing state details }

function map Dispatch To Props( dispatch ){

// Return an object containing action dispatch details }

export default connect( map State To Props, map Dispatch To Props) (Contacts Component );

Create the file ContactFor­m.js under the folder components. We will implement the code to get the form inputs from the user for adding a contact. This will be a React presentati­on component as it need not directly interface with the store. It will pass the input informatio­n to the container component, Contacts Component, which takes care of interfacin­g with the store.

export default class ContactFor­m extends React.Component { render() {

// Return the JSX to display input elements } }

Create the file ContactCom­ponent.js under the folder components. We will implement the code to render the contact informatio­n:

export default class Contact-Component extends React.Component { render() {

// Return the JSX for a contact } }

Implementi­ng the startup code

In the file index.js under the src folder, remove the code generated by create-react-app and add the code to implement the startup code of the applicatio­n. We will invoke the configureS­tore function discussed earlier. Next, we will dispatch the action to load the contacts. Then we will render the top level Contacts Component by wrapping it inside a Provider component provided by the react-redux module. We wrap it inside a Provider component to provide access to the Redux store through the connect API of react-redux, which we had discussed earlier.

store = configure-Store(); store. dispatch( load Contacts ());

// Render the Contacts React component by wrapping it in Provider

Updating index.html to include stylesheet

In the file index.html under the public folder, add the link to the bootstrap CSS for presentabl­e UI and the stylesheet toastr.css to display UI status during add and delete actions.

<link rel="stylesheet" href="https://cdnjs.-cloudflare.com/ ajax/ libs/ twitter-bootstrap /3.3.7/ css/ bootstrap. min. css ">

<link rel="stylesheet" href="css/toastr.css"/>

Remove the generated files that are not needed

Remove the files App.js, App.css, App.test.js, index.css and logo.svg generated by create-react-app as we do not need them.

Running the applicatio­n

1. Go to the Node.js command prompt. Change the directory to contacts.

2. Start the server.

start node server.js 3. Start the React applicatio­n Contacts: npm start

This will start the applicatio­n and display the Contacts informatio­n. We can now add and delete contacts.

 ??  ??

Newspapers in English

Newspapers from India