Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

Introducing MongoDB 8.0, the fastest MongoDB ever!
MongoDB Developer
MongoDB
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Productschevron-right
MongoDBchevron-right

Real Time Data in a React JavaScript Front-End with Change Streams

Joel Lord6 min read • Published Oct 04, 2022 • Updated Sep 09, 2024
ReactMongoDBChange StreamsJavaScript
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Some features mentioned below will be deprecated on Sep. 30, 2025. Learn more.
In many applications nowadays, you want data to be displayed in real time. Whether an IoT sensor reporting a value, a stock value that you want to track, or a chat application, you will want the data to automatically update your UI. This is possible using MongoDB Change Streams with the Realm Web SDK.
In this tutorial, you will learn how to use the Realm Web SDK to display changes in a collection as they happen.

Pre requisites

To follow this tutorial, you will need an Atlas cluster. The free tier will be more than enough for the needs of this tutorial. If you don't already have one, you can find the instructions on creating a cluster in the documentation.
Once you have a cluster, create a new database called data, with a collection changestream.
You will also need an app from Application Services. The instructions to create a new application can also be found in the documentation. Follow the instructions to create a new app without a template.

Configuring your Atlas App Services application

This application will display any operation that is performed on a specific collection. To do so, we will need to configure rules about who has access to the data (everybody) and how the users will authenticate (anonymously).

Note your application id

You will need your application ID when you start building your application. When you first open the application (or by clicking the navigation bar item with the name of your application), you will see the home page with the information about this application. Right at the top, you will notice a field labelled "App ID." This is your application id. 
Screenshot of the application id field in Atlas App Services You can either copy and paste it somewhere or just come back to this screen later when you'll need it.

Update the rules

From the left navigation menu in Atlas App Services, look for the "Rules" item. This will list all your databases and collections in the cluster associated with this application. Choose the data database and the changestream collection. You will be prompted to create a new role for this collection.
Screenshot of the rules UI in Atlas App Services
Use the readAll preset, and then click on the "Add preset role" button. This will create a new role that will have complete read access to the data in this collection. If you wanted to create a role that has only access to data owned by the user, this could be done with a custom role here.

Configure authentication

For this application, we won't require authentication, which means that any visitor to this website will have access to all the data. In our case, this is what we want, but in a production application, you might want to configure a real authentication provider.
In the left navigation bar, click on the "Authentication" item. In the displayed table, look for the "Allow users to log in anonymously" row.
Screenshot of the authentication providers
Click on the "Edit" button. On the next screen, toggle the "Provider Enabled" button to turn it on. After you click the Save button, go back to the authentication providers page and make sure it's enabled.

Deploy your changes

That's all you need in the Atlas App Services UI for now. Look for the blue bar at the top of the screen.
Screenshot of a message asking to review and deploy the changes
Click that "Review draft & deploy" button, and accept the changes.
Your application is now ready to be used.

Build the React application

We will start with a blank React application generated with the create-react-app tool for this application.
In your terminal, run the following command.
1npx create-react-app realm-web-changestreams
Next, install the required library to use the Realm Web SDK, and start the application.
1cd realm-web-changestreams
2npm install realm-web
3npm start
This will open up a browser window with the application running in it. With your favourite code editor, open up the source code for this application, and look for the App.js file.
You will replace the entire content of this file so you can go ahead and delete everything there.
Now, start with this boilerplate code for your App.js file.
1import React, {useState, useEffect} from "react"
2import * as Realm from "realm-web";
3
4// Create the Application
5
6// Define the App component
7
8const App = () => {
9 // Set state variables
10
11 // This useEffect hook will run only once when the page is loaded
12
13 useEffect(() => {
14
15 }, []);
16
17 // Return the JSX that will generate HTML for the page
18
19 return (
20   <div className="App">
21
22   </div>
23 );
24};
25
26export default App;
Under the comment Create the Application, enter the following.
1// Create the Application
2
3const app = new Realm.App({ id: "<YOUR_APP_ID>"});
This will instantiate your Atlas application. Don't forget to change the id to the identifier for your application.
Next, we will need two state variables. The first one —user— will contain the user object created by the Realm SDK once authenticated. The second one —events— will contain any new event from the database. Those events will be operations (create, update, or delete) performed on the database, along with the _id of the document and the full document.
Add the following code after the Set state variables comment.
1 // Set state variables
2 const [user, setUser] = useState();
3 const [events, setEvents] = useState([]);
Next up is the useEffect function. Here, you will create a function called login that will authenticate anonymously to the application. It will then update the user object in the state.
1 // This useEffect hook will run only once when the page is loaded
2
3 useEffect(() => {
4   const login = async () => {
5     // Authenticate anonymously
6     const user = await app.logIn(Realm.Credentials.anonymous());
7     setUser(user);
8
9     // Connect to the database
10     const mongodb = app.currentUser.mongoClient("mongodb-atlas");
11     const collection = mongodb.db("data").collection("changestream");
12
13     // Everytime a change happens in the stream, add it to the list of events
14     for await (const change of collection.watch()) {
15       setEvents(events => [...events, change]);
16     }
17   }
18   login();
19 }, []);
Finally, change the JSX code to render a table with the events.
1// Return the JSX that will generate HTML for the page
2 return (
3   <div className="App">
4       {!!user &&
5       <div className="App-header">
6         <h1>Connected as user ${user.id}</h1>
7         <div>
8           <p>Latest events:</p>
9           <table>
10             <thead>
11             <tr><td>Operation</td><td>Document Key</td><td>Full Document</td></tr>
12             </thead>
13             <tbody>
14           {events.map((e, i) => (
15             <tr key={i}><td>{e.operationType}</td><td>{e.documentKey._id.toString()}</td><td>{JSON.stringify(e.fullDocument)}</td></tr>
16           ))}
17           </tbody>
18           </table>
19         </div>
20       </div>
21       }
22   </div>
23 );
That's all you need for your application. If you look at your browser, you should see the application running.

Testing the application

In the Atlas UI, go ahead and create, edit, or delete items from the changestream collection. As you do those operations, you should see your new web application displaying each of those operations in real time as they happen.
Screenshot of the application in action
Note: When running this application, you might notice that some of the events are duplicated. This is due to the React.StrictMode tool which does a second pass on your code to notify you of any errors. This only happens in production, and won't happen if you run npm run build.

What about vanilla JavaScript?

The same application can be rewritten in plain old JavaScript under 50 lines. The main differences with the React application are that the realm-web is loaded via a script tag and that the code to build the table doesn't use JSX.
1<html>
2 <body>
3   <h1>Connected as user $<span id="userId"></span></h1>
4   <div>
5     <p>Latest events:</p>
6     <table>
7       <thead>
8         <tr><td>Operation</td><td>Document Key</td><td>Full Document</td></tr>
9       </thead>
10       <tbody id="tableBody"></tbody>
11     </table>
12   </div>
13 </body>
14
15 <!-- Import the Realm Web SDK -->
16 <script src="https://unpkg.com/realm-web/dist/bundle.iife.js"></script>
17
18 <script>
19   const main = async () => {
20     //Create the application
21     const app = new Realm.App({ id: "application-1-abcde" });
22
23     // Authenticate anonymously
24     const user = await app.logIn(Realm.Credentials.anonymous());
25     document.querySelector("#userId").textContent = user.id;
26
27     // Connect to the database
28     const mongodb = app.currentUser.mongoClient("mongodb-atlas");
29     const collection = mongodb.db("data").collection("changestream");
30
31     // Everytime a change happens in the stream, add it to the list of events
32     for await (const change of collection.watch()) {
33       let operationCell = document.createElement("td");
34       operationCell.textContent = change.operationType;
35       let keyCell = document.createElement("td");
36       keyCell.textContent = change.documentKey._id.toString();
37       let fullDocumentCell = document.createElement("td");
38       fullDocumentCell.textContent = JSON.stringify(change.fullDocument);
39       let eventRow = document.createElement("tr");
40       eventRow.appendChild(operationCell);
41       eventRow.appendChild(keyCell);
42       eventRow.appendChild(fullDocumentCell);
43       let tableBody = document.querySelector("#tableBody");
44       tableBody.appendChild(eventRow);
45     }
46   }
47   main();
48 </script>
49</html>

Summary

Change streams are a very powerful feature in MongoDB. They let you create applications that display and react to information in real time without needing a back-end.
If you want a little bit of an additional challenge, how about you build a chat application using Change Streams? Add a form that will use an Atlas HTTPS endpoint to add entries to the database, and then list the chat messages by listening for new changes in the collection.

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Article

Implementing Right to Erasure with CSFLE


Mar 08, 2023 | 7 min read
Quickstart

Getting Started With MongoDB & Mongoose


Aug 05, 2024 | 9 min read
Article

Unnecessary Indexes


Oct 01, 2024 | 4 min read
Tutorial

Secure your API with Spring Data MongoDB and Microsoft EntraID


Apr 02, 2024 | 8 min read
Table of Contents