Todos Example
Introduction
This example demonstrates how to create fullstack application with MERN stack. Application will handle a basic todo messages with text and date. User can add and delete todos.
Complete source codes: todo-example. Remember fork it first, if you are going to try it!
Application architecture
The image below shows the architecture of the application.
- Application UI uses HTML/CSS and JavaScript with React framework.
- Information is passed between the user interface and the server in JSON format.
- Node.js and Express technologies are used on the server side.
- Todos are stored in the MongoDB database in the cloud service.
Backend
Project and packages
Create a new todo\server
folder for a new Node.js project and install a below packages. You are using Express, Mongoose, dotenv to store environment variables and nodemon to restarting the node application when file changes in the directory are detected.
1 2 3 4 5 |
|
Modify your package.json
to include nodemon starting script:
package.json | |
---|---|
1 2 3 4 5 6 |
|
MongoDB in Atlas Cloud
You need to have an account to https://www.mongodb.com/. Create one free cluster, enable your IP, add database user/password. Create one database to use. Look more information from MongoDB materials.
Environment variables
Create .env
file to project root and add a following variables. You need to use your own Cloud MongoDB URI. Go to https://www.mongodb.com/ and login with your account. Go to your cluster/database and click connect to get your connection string. Select Connect your application and your connection string. Modify below to use your own connectin string.
.env | |
---|---|
1 2 |
|
Remember create .gitignore
file and add .env
and node_modules
into it, so those will not be published to Git clouds.
.gitignore | |
---|---|
1 2 |
|
Project starting code
Create index.js
file to create an Express application. Add one route/endpoint to your app.
index.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Start your server with nodemon:
1 |
|
Open your browser to http://localhost:3000/api/test to see that your api/test
endpoint is working (and your Node.js/Express app is running correctly!).
Connection to database
Create a new db
folder and a new mongodb.js
file inside it. As for the mongodb.js
, the database connection is separated and later imported in to index.js
. The parameters are used for supressing deprecation warnings when initiating the connection.
db/mongodb.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
And require it in index.js
and create a connection to MongoDB.
index.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Note
1 |
|
Save your files and nodemon should start your server again. You should see a following information in your terminal if connection to MongoDB is working correctly.
1 2 3 4 5 |
|
Todos model
Create a new models
folder and a new Todo.js
file into it.
User.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Use created Todo
model in your index.js
.
index.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
Routes
create a new todo
Create a new endpoint (for example below your api/test
endpoint) which will be used to communicate with MongoDB. We are getting data from the client (later) in the body of the POST request and pass it on to the models with create()
function, which is just a thin wrapper for the save()
function.
index.js | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Use Postman and create a few new Todo documents to your MongoDB database. Click image to see it better!
Remember check that data is correctly written to your MongoDB database.
get todos
Create an endpoint to get all todos from MongoDB database.
index.js | |
---|---|
1 2 3 4 5 6 7 8 |
|
Use Postman to get all todo documents from MongoDB database. Click image to see it better!
get todo
Create an endpoint which will return one todo by a todo id from MongoDB database.
index.js | |
---|---|
1 2 3 4 5 6 |
|
Use Postman to get one todo document from MongoDB database. Use one of your todo's id in request. Click image to see it better!
delete todo Create an endpoint which will be used to delete todo from MongoDB database.
index.js | |
---|---|
1 2 3 4 5 6 |
|
Use Postman to delete one todo document from MongoDB database. Use one of your todo's id in request. Click image to see it better!
Now deleted todo document is sent back to caller application (Postman). Remember check that todo document is deleted from MongoDB database.
Now backend programming should be ready and you can move on to client side coding.
Frontend
Introduction
The purpose of this exercise is to learn the basics of the React programming. You will create a small Todo app with create-react-app.
You will use this React app with your already made Node.js application which is using Express and Cloud based MongoDB database.
Create a new project
Your project structure will be as shown in below. You have separate folders for your client and backend side codes.
1 2 3 4 5 |
|
Go to your todo
folder and create a new React project called client. This code will create a client folder and React based application inside it. To get started go to your project client folder and start running development server.
1 2 3 4 |
|
Node server side app is running at port 3000
You might get a warning that something is already running on port 3000, which is default port for React app too. Just allow React to use another port instead. Your Node server side application (if it is running - should be ) is using port 3000.
1 2 3 4 5 |
|
Your browser should show a React based application running with a spinning blue React logo.
Modify App.js
Open App.js
in your Visual Studio Code editor and edit it to show “Hello React!” text. Save and see changes in your browser.
App.js | |
---|---|
1 2 3 4 5 6 7 |
|
You should see a below text in your browser.
Add a new Banner component to the app
React uses HTML elements which can be used in applications. Of course, you can create your own components/functions too.
Create a Banner
function, which will be used at the top of the ToDo app. Add a following code before App function. So, you can use multiple functions in the same file. Of course, you should separate all the functions/components to different files, if your project get’s bigger. Now our project is quite a small one.
App.js | |
---|---|
1 2 3 4 5 |
|
And remember use your Banner
in App
.
App.js | |
---|---|
1 2 3 4 5 6 7 |
|
Remove all the default styles from the App.css
file and use following styles. They will be used in this app.
App.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
Save you files and check your app in browser. Now a Banner
component should be visible at the top of the application.
Create an UI to show todos
A new todo will be asked with a HTML input element and all the todo items will be displayed within div element. Create a new ToDoFormAndList
function with a below code. Now ul
list will show some hardcoded values.
App.js | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
And remember use it in your App
rendering.
App.js | |
---|---|
1 2 3 4 5 6 7 8 |
|
Save you files and check your app in browser. Now a ToDoFormAndList
component should be visible at the below of the Banner
function. There are a few styles defined to input
elements in the styles. Look them from your App.css
. Now only a few hardcoded strings will be displayed in ul
list.
Load and show Todo items
First stop your server by clicking CTRL-C and install axios which can be used to communication between client and server side.
1 |
|
And use axios in your App.js
:
1 |
|
Start your server again with below command:
1 |
|
ToDoFormAndList
function should hold all the todo items in an array and a new item text. All these data should be saved in states, so you need to initialize these in your function. React Hooks will be used in this exercise.
Note
You will need to import React Hooks in your application. Modify you React import as shown below
import React, { useEffect, useState } from 'react';
Declare a new state variable to hold all todos inside ToDoFormAndList
function. It will be empty by default and it can be changed with setTodos
React Hooks function call.
App.js - ToDoFormAndList() | |
---|---|
1 |
|
Next use React Hooks useEffect
to load all todos from MongoDB database.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Save and run your code. You should get a following CORS error (open your browser inspector). That is normal behavior because we are running client and server in different resources in web. Read more information from here - CORS.
We need to use cors
middleware in Node/Express application to allow client request from different web origins.
First stop (cntr-c) your backend Node application and install cors
module and restart your backend application:
1 2 |
|
Modify your express application index.js
to use cors middleware.
index.js | |
---|---|
1 2 3 4 5 |
|
Refresh your React client application in browser and you should see loaded todos in your browser inspector (if you have some todos in your MongoDB database).
Next we will go back to the client side code and we will generate a list elements which will be used to show todos in UI.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Save and test your code. You should see todo items now below a new todo input field.
Now times are shown as they are stored in MongoDB database. We can use moment package to show those more nicely.
Stop your React app and install moment package. Start your React app again.
1 2 |
|
Import moment
in your React app and modify your todos date display:
App.js | |
---|---|
1 |
|
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 |
|
Save and test your code. Now dates are showm much nicer.
Add a new todo
Declare a new state variable to hold a new todo text inside ToDoFormAndList
function. It will be empty as a default and it can be changed with setNewTodoText
function call.
App.js - ToDoFormAndList() | |
---|---|
1 |
|
And use newTodoText
value inside a input
element. Add onChange
event to call React Hooks setNewTodoText
function to change newTodoText
text. Note how React Hooks can change variable state.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 |
|
Modify button
element to call own made addTodo
function when button is clicked.
App.js - ToDoFormAndList() | |
---|---|
1 |
|
And create addTodo
function inside ToDoFormAndList
function. Add a new item to items
and clears itemText
state.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 |
|
Check that your button event handling is working (open your browser inspector/console).
Next modify your code and use axios to send a new todo request to server side.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 |
|
Use your React app UI and add a new todo. Check response from your browser inspector.
Finally modify your code to add a new todo to your todos
and it will be automatically be visible in the UI because you will change the state of your todos
hooks.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Add a few todos. Remember check those are also stored in your MongoDB database.
Remove a todo
Add a new span
item's onClick
event to call removeTodo
function with selected todo._id
. Note that these _id
's are generated automatically in MongoDB database.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 |
|
Now todo list items will show a x
char which user can click to remove a todo.
Add removeTodo
function to your application. This function will use axios to send delete
method request to your server side REST API. After that a todo will be filtered away from todos
state collection and a new todos
state will be set and React will render component again.
App.js - ToDoFormAndList() | |
---|---|
1 2 3 4 5 6 7 8 9 |
|
Save your files and try to remove/add a few todos.
Final words
This exercise was a just a quick demo which shows how to create fullstack application with React, Node, Express and Mongo. This stack is called as a MERN stack.
You can modify this exercises to handle more features and add error checking. For example Mongoose validation is not used when a new todo is tried to save database.
Read More
Goals of this topic
Understand
- Understand the basic of the FullStack application development