Creating Application using MongoDB Realm (Stitch)(Part-2)

Yudhajit Adhikary
13 min readJan 11, 2021
Photo by Susan Yin on Unsplash

Hi Guys !, this article is the continuity of my previous article.

In part-1 we have discussed about the basic concept of mongoDB , we have developed our Product Store Application using MongoDB and React . Actually in part-1 we have build the application with the basic approach of MongoDB, creating backend using MongoDB, defining api and all , then creating frontend using React , and finally connecting the frontend and backend. If you have not checked my first blog please check that one first then you will understand the basic concept and what’s the difference between the two approach, the one we have applied in part 1 and the one we will be applying in part 2.So In part 2 we will be using Stitch a server less Query Api for building the same application we have developed in part 1 So that we can relate the difference between the approach clearly.

What is Stitch ?

Stitch is a server less platform for building application , it’s a collection of service offered by MongoDB Company, that we can use for building web application. So that a developer or we can focus on user interface and our code logic.

Stitch gives us access to MongoDB Atlas database access will be then available inside our client side application. It does explore our database credentials, it’s like our user can login or signup through stitch server . A user will use their own credentials to get access to the database, or we can lockdown what a single user can do. User are allowed to insert documents to their collection. We will authorize rights to our user, because they will not be having full access to the DB with mongoDB credentials which are not explored through Stitch. Stitch also react to events, if something gets inserted into a database, or something gets updated, we can run some code that gets triggered.

So How stitch actually works, stitch execute code or functionality in the cloud using stitch function and stitch services, which makes stitch server less. database is stitch query anywhere mongoDB mobile, stitch also reacts to events using stitch triggers.

So we will first see the previous architecture of mongoDB we had used in part 1.

Client (App) → (Node Api) → [MongoDB/Atlas]

Client App is our application, Node Js acts as the server between our client app and mongoDB database. For stitch that Node Api will get replaced by Stitch Server.

Client (App) → (Stitch Server) → [MongoDB/Atlas]

So enough theory , Now let’s start coding.

So App.js is the root component or the parent component of all other component for our application. Now , if you have gone through part-1 you will notice that we are not performing any api fetch or anything using axios. So we are using ‘mongodb-stitch-browser-sdk’ for including stitch server in our application, to install it we have to run : npm i mongodb-stitch-browser-sdk in our vscode terminal. We are importing Stitch, UserPasswordAuthProviderClient and UserPasswordCredential from mongodb-stitch-browser-sdk. These are client for interacting with username/password authentication provider in Stitch. So our App.js is having three parameter in state, isAuth to check whether the user is authenticated or not, authMode to determine whether user is logging in or signing up into our application and error to show error message. Now inside constructor we are configuring our client we are first initializing our default client id using Stitch.initializeDefaultAppClient. So from where we are getting this id ‘myshop-nareq’. To get the id we first have to add our project to MongoDB Realm. We have to first login to our MongoDB profile, there at the top we will be seeing Realm option. Click on that , then click on Create a New App button at top right . We will be seeing a form asking for Application name and Link for our Data Source. We can get a specific name, and add the cluster which we had created earlier for our application. Then we will click on Create button. Then a new app will be created in the MongoDB Realm , there on the top left we will see there will be App id , we will copy that id and will use that into our Stitch.initializeDefaultAppClient() function. We are calling callFunction , this callFunction() takes two parameters first one is function which will be defined into stitch function, and two parameter is the parameter we want to pass to that stitch function. To define the function we have to go to that realm dashboard, on the left side navigation tab there will be a function tab , click on that , then click on create a new function. On Function Editor tab , we will define our function.

exports = function(arg){
console.log(‘Greet!’,arg)
return {arg: arg};
};

We are just logging in console a message ‘Greet!’ .If we go to the logs tab in realm dashboard we will see that Greet! message whenever a user logs in. arg parameter gets the value which we pass on the client. callFunction() as second argument. logoutHandler() function is used to handle logging out from our application , there we are setting the isAuth state to false, we will be using those functions in other component or pages of our application. authHandler function is used to handle login. if user does not enter any details we will return our function. Else if the user have entered the details , we are creating user password authentication provider client using auth.getProviderClient() function. There we are passing UserPasswordAuthProviderClient.factory as parameter , UserPasswordAuthProviderClient is client for interacting with username/password authentication provider in Stitch. Now we are checking the authMode state , if it’s login we are creating the login credentials using the input fields data and calling UserPasswordCredential () function with the input field values. Then we are sending a request to make the user logged into our application using that credentials. Else if the user is signing up we are registering our user with the email id and password user has entered. So we are setting our request according to authMode state value, so our request will be a asynchronous function so if we are getting response that means user is authenticated ,we are setting the isAuth to true, But if there is any error we are setting isAuth to false. authModeChangedHandler() function is used to toggle the value of authMode between login and signup. errorHandler() function is used to set error message for our application. Now we will see the actual Dom structure of our application. Inside render we are first defining the routes of our application. We used to define all the routes and redirects (if any) inside Switch tag. So inside Switch tag we are first defining the redirects for base route ‘/’ user will be redirected to ‘/products’ routes, from ‘/auth’ and ‘signup’ also the user will be redirected to our products page. For path ‘/product/:mode’, mode value will be ‘add’ ,means for adding new products we will be using this route. So we are rendering our EditProductPage page and sending the response data and errorHandler function as props of the page. Similarly when the path is ‘/product/:id/:mode’ mode value will be ‘edit’ and id will be the object Id of the document (product) which we want to edit. Here also we are rendering EditProductPage page with the response data and errorHandler function as props of it. For route ‘products/:id’ id will be the object id of the particular product whose details will be shown into our product page, So there we are rendering our product page ProductPage with the response data and errorHandler function as props of it. ‘/products’ will be rendering our products page ( ProductPage ).But if our user is not authenticated means the isAuth state value is false, we will be defining a different route. We will redirecting our user from ‘/’ , ‘/product’ , ‘/products’ to ‘/auth’, we want our user to first login then continue with other pages. For the route ‘/confirm-account’ we are rendering our confirm account page. For the route ‘/auth’ we are rendering the our AuthPage , there we are passing our mode state , authHandler and authModeChangedHandler as props. Now we are finally rendering our Modal component which will appear whenever there is some error , there we are passing a custom title and errorHandler function as props and a paragraph as the child of it. Backdrop is used to make the background of our application blackish as the Modal opens. We have added our Header component , where we are passing isAuth state and logoutHandler function as props. And finally we are adding the routes variable which we have defined above. Now we create the rules means what our user can do in our application. To do that we have to go to the rules tab , then we have to click on Add Collection button, then we will be redirected to page where we will select the database and collection name for which we want to set the rules. For permission template we will keep it No template for now. This will create the rules of our application for the read/ write permission in product collection. Then we can see there will a tabular representation of rules which got applied to the product collection, we can check or uncheck the options of read and write to set rules for product collection. We can also specify the read write rules for specific field in product collection by clicking on Add Field button. Now we will specify how the user authentication or login will happen for our application. For that we have to go to Authentication tab , there we will select the authentication type we want, we will select Email/Password by clicking on edit button . Provider Enabled will be ON, we can also send a confirmation mail to that email id, for that select User Confirmation Method to Send a confirmation email. There should be one Email confirmation Url, which should point to a page that contains the email confirmation script. Realm will automatically append the user token and tokenId to that Url in the email. So we are passing account confirmation page url http://localhost:3000/confirm-account , so realm will automatically append the token and token Id to that url and user will automatically get redirected to our homepage. Now let’s see the pages of our application. We will start with Auth.js.

In Auth.js we are defining our authentication page. So state will be having two parameters email and password. inputChangeHandler is the function which is used to set our state values according to the values we will be entering in our input fields. Now we are checking value of mode for setting value of our modeButtonText and submitButtonText variable accordingly. This page will be having a button for login or signup, onClick of this we are calling onAuthModeChange function from props. Now inside the form we are having input fields for email and password. onChange of each input fields we are calling inputChangeHandler function with the input field name and event object. We are also having the button for submitting the form. onSubmit of the form we are calling onAuth function from props, with the object having input field values of email and password as the parameter . Now we will be looking into the confirmAccount page.

So confirm Account page will actually perform the confirmation of the email id. When user submits the email id and password for signup . A confirmation mail will be send to that email id. That mail will be having a url http://localhost:3000/confirm-account/:token/:tokenid, token and tokenId while be provided by realm, when user clicks on that link , user gets redirected to the homepage, which indicates the email confirmation is successful. So this functionality happens in this confirmAccount.js. In confirmAccount.js componentDidMount() we are storing the url of the page in a constant called queryUrl , then we are storing the params of the url in queryParams. then we are fetching the token and tokenId from the params, and storing those in token and tokenId constant respectively. Now are creating authentication client by using auth, getProviderClient function and named it emailPassClient. Our user email id is confirmed by passing the token and tokenId to emailPassClient.confirmUser function. If there is no error means user email confirmation is successful we are redirecting our user to our homepage ‘ / ’ . So in confirmation page we want to show our user the Loading message when the confirmation is running until the user gets redirected to the homepage of our application, for that we are just rendering main tag with the message Confirming Account….. ,Now we will be see our Products.js .

In Products.js we are defining our Products page. There are two parameter in our states , isLoading and products. when the page renders in componentDidMount() we are calling fetchData() function. fetchData() function actually fetches the data from our database, so in fetchData () we are first defining our service client called mongodb. Now we are accessing products collection in shop database , then we are fetching the data in array format, when we got the response we are setting our isLoading state to false and passing the response to our isLoading state. If there is any error we are setting isLoading state to false and calling the OnError function from props with the error message. We also have another function productDeleteHandler() to handle the delete functionality of our products. In productDeleteHandler( ) function we are creating service client for our database called mongodb. Then we are accessing products collection in shop database and deleting product having id same as productId. Once deletion is done we are calling fetchData() function. Now we are defining the content, initially we are defining the content as Loading products.. .When isLoading is false and products are available, we are setting content as Products component which is having products state and productDeleteHandler() function as props. If isLoading is false and there is no products we are setting content as paragraph having text ‘Found no products, Try again later’. Finally we are rendering the content inside main tag. Now let’s see the Product.js.

In Product.js we are designing our product details page. We have two parameter in states isLoading and product. So when the page loads in componentDidMount() we are fetching the details of the particular product . We are creating service client for our database called mongodb. Then we are accessing products collection in shop database and fetching product having id same as id coming from params of the page url. Once we get the data of that particular product we are converting product id and price into string, then we are setting our isLoading state to false and passing the response data to our product state. If there is any error we will be setting isLoading state to false, and will be calling onError() function with error message. We are rendering content variable , so initially our page will show ‘Is loading…’. If isLoading is false , and product details is fetched , we are setting content to main tag having product name, price, product image and description. If isLoading is false and there is no product details , we will show paragraph having text ‘Found no product. Try again later’. Now we will be seeing the Edit Product page.

In EditProduct.js , we are creating add product and edit product page of our application. We are importing our Input and Button component. So our ProductEditPage is having 5 parameters in state , isLoading , title, price, imageUrl and description. When our page renders , in componentDidMount we will be checking whether the user is adding new product or editing existing product for that we are checking this.props.match.params.mode if it is equal to ‘edit’, We are creating service client for our database called mongodb. Then we are accessing products collection in shop database and fetching product having id same as id coming from params of the page url. Once we get all the details of our product we are setting our isLoading state to false, title to product name, price to product price , imageUrl to product.image and description to product description. If this.props.match.params.mode is not equal to ‘edit’ we will just set our isLoading to false. editProductHandler() function is used to edit or add products in our application. We will be first do error checking if the user have not entered any thing and clicks on the submit button we will just simply return the function we will not perform anything. If user enters all the details and submit the form we will first set the isLoading state to true, we will create an object productData with all the input fields values. Then we will be creating our request based on the value of mode present in our url (this.props.match.params.mode). If mode is equal to ‘edit’ we are calling updateOne function on products collection , updateOne have two arguments first argument is the condition for determining in which product the update should happen and second parameter is having the updated product data . But if it is not then it means the user is actually adding new products for that we are creating our service client and inserting the productData or newly added product details in our products collection. Once we get the response we will set isLoading state to false, and redirecting our page to products page. If there is any error , we are setting isLoading states to false and calling our onError() function with error message. inputChangeHandler() function is used to set our state value with the input field value. So inside render we will setting our content, So our content will be a form having input fields for product title, price, image, description. For each fields we are passing the config object, label, elType, and on onChange() function we are calling inputChangeHandler function with event object and label of each input field. Then we are having button to submit the edit /add product form , on submission of the form we are calling editProductHandler() function. If this.state.isLoading is true we will set content to paragraph having text ‘Is loading…’.And finally render our content inside main tag. So our application is up now let’s have a look.

So we can see how easily we can create our application using MongoDB Stitch, We don’t have to config any backend or Api , Stitch takes care of it. This is just a basic implementation we can utilize many cool features which are provided by Stitch in our application. The main advantage of Stitch is that developer do not have to worry for the backend creation or connection , this will give them more time to think about user interface and coding logics. I am attaching my github repo and documentation of MongoDB as reference of this article.

Code :

Documentation:

HAPPY CODING….:)

--

--

Yudhajit Adhikary

Web developer by profession,Photographer,Blog Writer,Singer,Pianist,Seeker of Solution