Hey there, Today we will proceed to create a demo for CRUD with React, Express, Node.js and MongoDB(MERN Stack).
Below are the requirements for creating the CRUD on MERN
- Node.js
- React.js
- Mongodb
- IDE or Text Editor
I assume that you have already available the above tools/frameworks and you are familiar with all the above that what individually actually does.
As we know that we can easily start working on React.js with create-react-app tool. Here I will skip this, Because you would be familiar with the basic stuff of React.js. If you are not aware of creating React.js app with the above tool. React my article on it Getting Started with React.js
Let's Get Started
Step 1: Configure React Routing after creating React.js app
In this sample application, I will show here CRUD operation of documents having three input fields in it. After setting app the React basic app we need to install the next dependency with the below command:
npm install react-router-dom --save
Step 2: Create needed components and service
At first, create a folder named components inside the src folder and create different component files needed for CRUD operations. Create Service file named Document Service.js and put the below code inside it for making all HTTP request:
// import React from 'react';
import axios from 'axios'
const baseUrl="http://localhost:3001/document/"
class DocumentService {
static postApi(url,data){
return axios.post(baseUrl + url, data);
}
static getApi(url){
return axios.get(baseUrl + url);
}
static deleteApi(url){
return axios.delete(baseUrl + url);
}
}
export default DocumentService
Code AddDocument.js file
import React from 'react';
import DocumentService from './DocumentService';
class AddDocument extends React.Component{
constructor(props){
super(props)
this.state = {
document_title:'',
desc:'',
publisher: ''
}
}
addDoc=()=>{
DocumentService.postApi('create-document',{document_title:this.state.document_title,desc:this.state.desc,publisher:this.state.publisher})
.then(json => {
if(json.data.statusCode===200){
this.props.history.push('/index')
}
else{
alert('something went wrong!!');
this.props.history.push('/index')
}
}).catch((error)=>{
console.log("error-----------",error)
})
}
handleChange= (e)=> {
this.setState({[e.target.name]:e.target.value});
}
render() {
return (
<div>
<h2 className="text-center">Add Document Form</h2>
<div className="row justify-content-md-center">
<div className="col-md-6 col-md-offset-3">
<form>
<div className="form-group">
<label>Title:</label>
<input name="document_title" type="text" className="form-control" onChange={this.handleChange} value={this.state.document_title}></input>
</div>
<div className="form-group">
<label>Description:</label>
<input name="desc" type="text" className="form-control" onChange={this.handleChange} value={this.state.desc}></input>
</div>
<div className="form-group">
<label>Publisher:</label>
<input name="publisher" type="text" className="form-control" onChange={this.handleChange} value={this.state.publisher}></input>
</div>
<button type="button" onClick={this.addDoc} className="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
);
}
}
export default AddDocument;
In the above file, We have form with three fields title, description and publisher. Inside the constructor, We have set the variable in the state which will be updated with the help of handleChange method call on onChange event of input field. You can read official doc to know more about the state and props.
Code for ListDocument.js file
import React, { Component } from 'react';
import DocumentService from './DocumentService';
import axios from 'axios';
import TableRow from './TableRow';
import {Link} from 'react-router-dom';
let styles = {
marginTop: '100px'
};
class ListDocument extends Component {
constructor(props) {
super(props);
this.state = {value: '', items: ''};
this.addDocumentService = new DocumentService();
}
componentDidMount(){
axios.get('http://localhost:3001/document/get-document')
.then(response => {
this.setState({ items: response.data });
})
.catch(function (error) {
console.log(error);
})
}
tabRow(){
if(this.state.items instanceof Array){
return this.state.items.map(function(object, i){
return <TableRow obj={object} key={i} />;
})
}
}
render() {
return (
<div className="container" style={styles}>
<h3>List of Documents</h3>
<Link to={"/add-document/"} >Add New Document</Link>
<table className="table table-striped">
<thead>
<tr>
<td>Title</td>
<td>Description</td>
<td>Publisher</td>
<td></td>
</tr>
</thead>
<tbody>
{this.tabRow()}
</tbody>
</table>
</div>
);
}
}
export default ListDocument;
In the above file, We are calling list of document, We are using axios for making HTTP request. And document service is imported for all the http request. Also we can call the data in the component which I have tried to show you in the above file. You may think this a mistake but its made in the way to clear the concept for beginner level programmer. Apart from the above imports, we have imported TableRow for binding the fetched data with template.
Code for TableRow.js
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import DocumentService from './DocumentService';
import { withRouter } from 'react-router';
class TableRow extends Component {
constructor(props) {
super(props);
}
deleteDocument= () =>{
DocumentService.deleteApi('delete-document?id='+this.props.obj._id)
.then(json => {
if(json.data.statusCode===200){
alert('Record deleted successfully!!');
this.props.history.push('/add-document')
}
else{
alert('something went wrong!!');
this.props.history.push('/index')
}
}).catch((error)=>{
console.log("error-----------",error)
})
}
render() {
return (
<tr>
<td>
{this.props.obj.document_title}
</td>
<td>
{this.props.obj.desc}
</td>
<td>
{this.props.obj.publisher}
</td>
<td>
{this.props.obj.item}
</td>
<td>
<Link to={"/edit-document/"+this.props.obj._id} className="btn btn-primary">Edit</Link>
</td>
<td>
<form >
<button type="button" onClick={this.deleteDocument} className="btn btn-danger">Delete</button>
</form>
</td>
</tr>
);
}
}
export default withRouter(TableRow);
Code for EditDocument.js
import React, { Component } from 'react';
import axios from 'axios';
import DocumentService from './DocumentService';
class EditDocument extends Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.state = {
document_title:'',
desc:'',
publisher: ''
}
}
componentDidMount(){
axios.get('http://localhost:3001/document/get-document-by-id?id='+this.props.match.params.id)
.then(response => {
this.setState({
document_title: response.data.document_title,
desc: response.data.desc,
publisher: response.data.publisher
});
})
.catch(function (error) {
console.log(error);
})
}
handleChange= (e)=> {
this.setState({[e.target.name]:e.target.value});
}
editDoc=()=>{
console.log(this.props.match.params.id,'--id')
DocumentService.postApi('update-document',{document_title:this.state.document_title,desc:this.state.desc,publisher:this.state.publisher,id:this.props.match.params.id})
.then(json => {
console.log(json,'response on edit request!!!!!');
if(json.data.statusCode===200){
alert('Record updated successfully!!')
this.props.history.push('/index')
}
else{
alert('something went wrong!!');
this.props.history.push('/index')
}
}).catch((error)=>{
console.log("error-----------",error)
})
}
render() {
return (
<div>
<h2 className="text-center">Edit Document Form</h2>
<div className="row justify-content-md-center">
<div className="col-md-6 col-md-offset-3">
<form>
<div className="form-group">
<label>Title:</label>
<input name="document_title" type="text" className="form-control" onChange={this.handleChange} value={this.state.document_title}></input>
</div>
<div className="form-group">
<label>Description:</label>
<input name="desc" type="text" className="form-control" onChange={this.handleChange} value={this.state.desc}></input>
</div>
<div className="form-group">
<label>Publisher:</label>
<input name="publisher" type="text" className="form-control" onChange={this.handleChange} value={this.state.publisher}></input>
</div>
<button type="button" onClick={this.editDoc} className="btn btn-primary">Submit</button>
</form>
</div>
</div>
</div>
);
}
}
export default EditDocument;
Now our component and service related task is done, In the above files we have created service for making HTTP request. And separate files for adding a document, listing documents, edit document. Now the next thing is to set the route
Step 3: Update index.js
Open index.js file under src and put the below code.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
// import App from './App';
import AddDocument from './components/AddDocument';
import ListDocument from './components/ListDocument';
import EditDocument from './components/EditDocument';
ReactDOM.render(
<Router>
<div>
<Route exact path='/' component={ListDocument} />
<Route path='/add-document' component={AddDocument} />
<Route path='/index' component={ListDocument} />
<Route path='/edit-document/:id' component={EditDocument} />
</div>
</Router>,
document.getElementById('root')
);
We are almost done with the code needed to do at client end.
Step 4: Create Server
Since I have already posted an article for CRUD application with angular. So please follow article from there for creating server for CRUD application Angular6 CRUD Application with NodeJS and Mongodb
Step 5: Start the client and server
After completing all these steps, We need to start the client app and server app over the terminal in the project folder
npm start // for react app
node server.js // for nodejs app
Over the browser we will have page like below:
Document list page
Add document page will look like below over the browser:
Conclusion
So in this article, We learn to create CRUD application in React.js step by step with much less code. You can also find other demos of React.js Sample Projects here to start working on enterprise level application.
That’s all for now. Thank you for reading and I hope this demo will be very helpful for CRUD Application in React Example and Tutorial application.
Let me know your thoughts over the email demo.jsonworld@gmail.com. I would love to hear them and If you like this article, share with your friends.