Your First App using React with Express and MongoDB





5.00/5 (2 votes)
Your first App using React with Express and MongoDB
In one of our previous MEAN Stack tutorials, we followed a step by step approach to develop a RESTful API using ExpressJS with MongoDB. Here in this MEAN Stack article, we are going to develop another application in ExpressJS and MongoDB with ReactJS. We will follow the same step by step approach to build this application.
Now, let's move further to start developing our application using ReactJs with Express and MongoDB.
STEP 1: Initialize the Project
- Create a folder with the project name such as todoapp.
- Open command prompt window on the project folder.
- Run the following command:
npm init
This command will create a package.json file with the following details:
STEP 2: Install Express
- Install express with following command:
npm install express --save
STEP 3: Install Express Generator
- Install express-generator using the following command:
npm install express-generator --save
STEP 4: Create the Project
- Use the following command to create the express project:
express hello-mern
This will give the following output:
create : todoapp create : todoapp/package.json create : todoapp/app.js create : todoapp/public create : todoapp/routes create : todoapp/routes/index.js create : todoapp/routes/users.js create : todoapp/views create : todoapp/views/index.jade create : todoapp/views/layout.jade create : todoapp/views/error.jade create : todoapp/public/stylesheets create : todoapp/public/stylesheets/style.css create : todoapp/public/javascripts create : todoapp/public/images create : todoapp/bin create : todoapp/bin/www install dependencies: $ cd hellomern && npm install run the app: $ DEBUG=hellomern ./bin/www
STEP 5: Setup Development Dependencies
- Add the following dependencies and dev dependencies in package.json file and run
npm install
from the root folder of the project.{ "name": "hello-mern", "version": "0.0.0", "private": true, "scripts": { "start": "webpack --progress --colors --watch -d", "build": "webpack --progress --colors -p" }, "dependencies": { "axios": "^0.15.3", "babel-cli": "^6.11.4", "babel-core": "^6.13.2", "babel-preset-es2015": "^6.13.2", "babel-preset-react": "^6.11.1", "body-parser": "~1.16.0", "cookie-parser": "~1.4.3", "debug": "~2.6.0", "ejs": "^2.5.6", "express": "~4.14.1", "jade": "~1.11.0", "mongojs": "^2.4.0", "morgan": "~1.7.0", "react": "^15.4.2", "react-bootstrap": "^0.30.7", "react-dom": "^15.4.2", "react-router": "^2.6.1", "serve-favicon": "~2.3.2" }, "devDependencies": { "babel-loader": "^6.2.10", "http-server": "^0.9.0", "webpack": "^1.13.3" } }
STEP 6: Setup ReactJs Build Dependencies:
- In package.json, add the following script and dev-dependencies.
"scripts": { "start": "node ./bin/www", "start": "webpack --progress --colors --watch -d", "build": "webpack --progress --colors -p" }, "devDependencies": { "babel-loader": "^6.2.10", "http-server": "^0.9.0", "webpack": "^1.13.3" }
- Config the webpack.config.js file as follows:
var webpack = require('webpack'); var definePlugin = new webpack.DefinePlugin({ __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')), __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false')) }); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); module.exports = { cache: true, entry: { main: './views/index.jsx' }, output: { path: 'public/build', filename: '[name].js' }, module: { loaders: [ {test: /\.jsx?$/, loader: 'babel', exclude: /(node_modules|bower_components)/, query: { presets: ['react', 'es2015'] }}, ] }, resolve: { extensions: ['', '.js', '.jsx'] }, plugins: [ definePlugin, commonsPlugin ] };
- From command prompt, run '
npm start
'. This will create a new directory called build inside public folder. and the following files will be there: - Create index.html file inside public folder.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> <title>MERN</title> <meta name="viewport" content="width=device-width"> <link rel="stylesheet" href="./stylesheets/style.css" /> <link rel="stylesheet" href="./stylesheets/App.css" /> <script src="./build/common.js"></script> </head> <body> <div id="root"></div> <script src="./build/main.js"></script> </body> </html>
- Change the routes in routes/index.js as follows:
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { // res.render('index', { title: 'Express'}); this is the old line res.render('index.html'); }); module.exports = router;
- Change the
app-engine
in app.js.// view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); app.engine('html', require('ejs').renderFile);
- Create an index.jsx in /views folder:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render( <App />, document.getElementById('root') );
- Create a App.jsx in /views folder:
import React, { Component } from 'react'; class App extends Component { render() { return ( <div className="App"> <div className="App-header"> <img src="./images/logo.svg" className="App-logo" alt="logo" /> <h2>Welcome to React+ Express +Mongo</h2> </div> </div> ); } } export default App;
- From browser, run http://localhost:3000/:
STEP 7: Run Mongo
- Run mongodb.exe - it will start the mongodb.
- Connect to
todoapp
database using the following command:
STEP 8: Develop the Server-side
- Create the server REST API in routes/todo.js:
var express = require('express'); var router = express.Router(); var mongojs = require('mongojs'); var db = mongojs('mongodb://localhost:27017/todoapp', ['todos']); // Get All todos router.get('/todos', function(req, res, next){ db.todos.find(function(err, todos){ if(err){ res.send(err); } res.json(todos); }); }); // Get Single Task router.get('/todo/:id', function(req, res, next){ db.todos.findOne({_id: mongojs.ObjectId(req.params.id)}, function(err, todo){ if(err){ res.send(err); } res.json(todo); }); }); //Save todo router.post('/new', function(req, res, next){ var todo = req.body; if(!todo.title || !(todo.isDone + '')){ res.status(400); res.json({ "error": "Bad Data" }); } else { db.todos.save(todo, function(err, todo){ if(err){ res.send(err); } res.json(todo); }); } }); // Delete todo router.delete('/todo/:id', function(req, res, next){ db.todos.remove({_id: mongojs.ObjectId(req.params.id)}, function(err, todo){ if(err){ res.send(err); } res.json(todo); }); }); // Update todo router.put('/todo/:id', function(req, res, next){ var todo = req.body; var updtodo = {}; if(todo.isDone){ updtodo.isDone = todo.isDone; } if(todo.title){ updtodo.title = todo.title; } if(!updtodo){ res.status(400); res.json({ "error":"Bad Data" }); } else { db.todos.update({_id: mongojs.ObjectId(req.params.id)},updtodo, {}, function(err, todo){ if(err){ res.send(err); } res.json(todo); }); } }); module.exports = router;
STEP 9: Develop the Client-side
- Add model:
//mode/todo.js 'use strict'; //import dependency var mongoose = require('mongoose'); var Schema = mongoose.Schema; //create new instance of the mongoose.schema. the schema takes an object that shows //the shape of your database entries. var TodoSchema = new Schema({ title: String, description: String, priority: String, duedate: String, status: String }); //export our module to use in server.js module.exports = mongoose.model('Todo', TodoSchema);
- Add Form Component '
TodoForm
'.import React, { Component } from 'react'; import style from './style'; export default class TodoForm extends Component { constructor(props) { super(props); this.state = { author: '', text: '' }; this.handleSubmit = this.handleSubmit.bind(this); } handleSubmit(e) { e.preventDefault(); let author = this.state.author.trim(); let text = this.state.text.trim(); if (!text || !author) { return; } this.props.onCommentSubmit({ author: author, text: text }); this.setState({ author: '', text: '' }); } render() { return ( <div> <h1> Add new Todo</h1> <form onSubmit={ this.handleSubmit }> <div className="form-group"> <label for="exampleInputEmail1">Title</label> <input type="text" className="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Title"/> </div> <div className="form-group"> <label for="exampleSelect1">Priority</label> <select className="form-control" id="exampleSelect1"> <option>High</option> <option>Medium</option> <option>Normal</option> </select> </div> <div className="form-group"> <label for="exampleTextarea">Description</label> <input type="text" className="form-control" id="exampleTextarea"placeholder="Description"/> </div> <div className="form-group"> <label for="datetimepicker1">Due date</label> <div className='input-group date' id='datetimepicker1'> <input type='text' className="form-control" /> <span className="input-group-addon"> <span className="glyphicon glyphicon-calendar"></span> </span> </div> </div> <button type="submit" className="btn btn-primary">Add</button> <button type="cancel" className="btn btn-danger">Cancel</button> </form> </div> ) } }
- Add List Component:
import React, { Component } from 'react'; export default class TodoList extends Component { render() { let todoNodes = this.props.data.map(todo => { return ( <div className="panel panel-primary"> Title : {todo.title} </div> ) }) return ( <div className="panel panel-success"> <h1> All Todos </h1> { todoNodes } </div> ) } }
- Update App.jsx:
import React, { Component } from 'react'; import style from './style'; import TodoForm from './TodoForm'; import TodoList from './TodoList'; import axios from 'axios'; class App extends Component { constructor(props) { super(props); this.state = { data: [] }; this.loadTodosFromServer = this.loadTodosFromServer.bind(this); this.handleTodoSubmit = this.handleTodoSubmit.bind(this); this.handleTodoDelete = this.handleTodoDelete.bind(this); this.handleTodoUpdate = this.handleTodoUpdate.bind(this); } loadTodosFromServer() { axios.get(this.props.url) .then(res => { this.setState({ data: res.data }); }) } handleTodoSubmit(comment) { let comments = this.state.data; comment.id = Date.now(); let newComments = comments.concat([comment]); this.setState({ data: newComments }); axios.post(this.props.url+'/todo/'+comment.id, comment) .catch(err => { console.error(err); this.setState({ data: comments }); }); } handleTodoDelete(id) { axios.delete(`${this.props.url}/${id}`) .then(res => { console.log('Comment deleted'); }) .catch(err => { console.error(err); }); } handleTodoUpdate(id, comment) { //sends the comment id and new author/text to our api axios.put(`${this.props.url}/${id}`, comment) .catch(err => { console.log(err); }) } componentDidMount() { this.loadTodosFromServer(); setInterval(this.loadTodosFromServer, this.props.pollInterval); } render() { return ( <div className="App"> <div className="App-header"> <img src="./images/logo.svg" className="App-logo" alt="logo" /> <h2>Welcome to React+ Express +Mongo</h2> </div> <TodoList onTodoDelete={ this.handleTodoDelete } onTodoUpdate={ this.handleTodoUpdate } data={ this.state.data }/> <TodoForm onTodoSubmit={ this.handleTodoSubmit }/> </div> ); } } export default App;
- Update index.jsx:
import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.render( <App url='http://localhost:3000/todos' pollInterval={2000}/>, document.getElementById('root') );
- From browser:
Hopefully, this application will be helpful in understanding the technology in a practical manner and developing the first application using React.js with Express and MongoDB.
Top Related Technical Articles
- Top 20 AngularJS Interview Questions
- All you need to know about Angular 2.0 (FAQs Series)
- Top 15 Bootstrap Interview Questions
- All about NodeJS – Start to End
- Top 10 HTML5 Interview Questions
- Top ReactJS Interview Questions
The post Your first App using React with Express and MongoDB appeared first on Web Development Tutorial.