{{announcement.body}}
{{announcement.title}}

How to Use Backendless With React.js: Real-Time Database Integration Tutorial

DZone 's Guide to

How to Use Backendless With React.js: Real-Time Database Integration Tutorial

You can't have an effective web app without a database. Read on to learn how to hook one up to the React application we're building.

· Web Dev Zone ·
Free Resource

React.js development

This is the third part of our series on using Backendless with a React.js frontend app. You can catch up on the previous articles here: Part 1 and Part 2. If you'd like to jump in now, you can simply create a new Backendless app, clone our previous progress from our repository, and use this commit as an entry point for today's article.

Our goal for today is to showcase integration with our Real-Time (we call it RT) database for delivering changes in your data table from the server to the client. We have previously written about implementation of RT in an Angular app ( "How to Use the Backendless Real-Time Database in Your Angular App"). If you're interested in Angular or you just want to see difference between the usage of RT with React and Angular, we'd recommend you give that article a read.

What Is Real-Time (RT) Database?

As discussed in our Angular series, in most cases, you want your application to display the most up-to-date data without any additional requests to the server. There are three events that, once they occur, sync your client's app with the server data:

  • create - this event is delivered to the client app when a new object is created on the server.
  • update - this event is delivered to the client app when an existing object is changed on the server.
  • delete - this event is delivered to the client app when an existing object is deleted on the server.

All of our SDKs (JS, Android, and iOS) have been updated with the logic necessary to establish a connection to our Real-Time servers and provide you with the ability to subscribe to the events shown above.

Check out the Real-Time Database API documentation for more information.

Subscribe for Real-Time (RT) Changes

Generally, to have up-to-date data, we need three subscriptions/listeners as mentioned above:

  • Listener for create record in the database.
  • Listener for update record in the database.
  • Listener for delete record in the database.


Also, there are may be a case when we need to listen for only one kind of change. For example, let's say we have a Message table and we know that there is no way to remove or update records on the server. Therefore, we only need to subscribe for create objects. As another example, say we have a table and we would only like to receive changes to current users. In this case, we need only the subscription for the update object.

In our app, we will use all of the subscription types in order to keep our Persons collection up-to-date.

As you know from the previous articles in this series, we use Redux for our app data store. In order to deliver changes from the server to the redux store, we need to have three additional actions for each RT subscription. Let's create them in ./src/store/actions/persons.js:

export const onPersonCreate = person => ({
person,
type: t.ON_PERSON_CREATE,
});

export const onPersonUpdate = person => ({
person,
type: t.ON_PERSON_UPDATE,
});

export const onPersonRemove = person => ({
person,
type: t.ON_PERSON_REMOVE,
});

Don't forget to add action types for these actions.

Now we are going to add reducers for the above actions, but before we do that, we have to look out for a duplication issue. As we've already implemented reducers for changing the store when we create/update/delete persons, and now we're going to add RT actions, we will see duplication of persons in the store. For example, when we create a new person:

  • Reducer action  t.CREATE_PERSON_SUCCESS  will put the new created person into the store.
  • RT action t.ON_PERSON_CREATE will put the new created person into the store as well.

To avoid this scenario, we should adjust the Persons reducers. Let’s replace the current code in ./src/store/reducers/persons.js with the following:

import t from '../action-types'
import { reduceReducers, loadReducer, reducersMap } from './helpers'

const initialState = {
list: []
};

const personsReducer = reduceReducers(initialState,
loadReducer(t.LOAD_PERSONS, (state, action) => ({
  ...state,
  list: action.result
})),

reducersMap({
  [t.CREATE_PERSON_SUCCESS]: (state, action) => addPerson(state, action.result),
  [t.UPDATE_PERSON_SUCCESS]: (state, action) => updatePerson(state, action.result),
  [t.REMOVE_PERSON_SUCCESS]: (state, action) => deletePerson(state, action.personId),

  [t.ON_PERSON_CREATE]: (state, action) => addPerson(state, action.person),
  [t.ON_PERSON_UPDATE]: (state, action) => updatePerson(state, action.person),
  [t.ON_PERSON_REMOVE]: (state, action) => deletePerson(state, action.person.objectId)
})
);

function addPerson(state, person) {
if (state.list.find(p => p.objectId === person.objectId)) {
  return state
}

return {
  ...state,
  list: state.list.concat(person)
}
}

function updatePerson(state, person) {
return {
  ...state,
  list: state.list.map(p => p.objectId === person.objectId ? person : p)
}
}

function deletePerson(state, personId) {
return {
  ...state,
  list: state.list.filter(person => person.objectId !== personId)
}
}

export default personsReducer


Finally for today, let’s add RT subscriptions in ./src/persons/index.js file. To do so:

  • Import Backendless JS-SDK module.
  • Import RT actions.
  • Modify  componentWillMountmethod.
  • Add  componentWillUnmount method.
import Backendless from 'backendless';

import { loadPersons, getPersons, onPersonCreate, onPersonUpdate, onPersonRemove } from '../store';
componentWillMount(){
this.props.loadPersons();

this.personRT = Backendless.Data.of('Person').rt();

this.personRT.addCreateListener(this.props.onPersonCreate);
this.personRT.addUpdateListener(this.props.onPersonUpdate);
this.personRT.addDeleteListener(this.props.onPersonRemove);
}

componentWillUnmount(){
this.personRT.removeCreateListener(this.props.onPersonCreate);
this.personRT.removeUpdateListener(this.props.onPersonUpdate);
this.personRT.removeDeleteListener(this.props.onPersonRemove);
}
export default connect(mapStateToProps, { loadPersons, onPersonCreate, onPersonUpdate, onPersonRemove })(Persons);

Real-Time Demo

Time to take it for a test drive. Let's see how it works:

Conclusion

Surprisingly easy, wasn't it? We just used a very basic case, but there are many cases where RT could be vital. If you have any questions or are looking for a specific solution with RT, please leave us a comment or create a new support topic on our support forum. Thanks for reading! Everything we have done today can be found in this commit.



If you enjoyed this article and want to learn more about React, check out this collection of tutorials and articles on all things React.

Topics:
web dev ,react.js tutorial ,database integration ,real-time data integration

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}