原文链接:Let’s build a full stack MongoDB, React, Node and Express (MERN) app

github源码地址:jelorivera08/react_fullstack

from being a Front End Developer to a Full Stack Developer

I’ve included the git repository link of the whole code at the end of the article but I suggest that you take this article step-by-step before checking the repo out.

The front end allows us to view the current information inside our database. It also allows us to add new data into it, delete a present data and update an already existing one.

We will build it from nothing. We will setup our own database, create the back end from the ground up(from the ground up:从头开始) and bootstrap our front end with the bare minimum.

First Things First

Let’s create our project’s main directory. This will hold both the code for the front and back end of our app.

mkdir fullstack_app && cd fullstack_app

Then, let’s start off with our front end.

We will use create-react-app to bootstrap our front end, which means that we will not have to worry about setting up Webpack or Babel (as create-react-app sorts this all out by default).

If you don’t have create-react-app globally installed yet, fret not, installing it is easy, just type this into our project’s main directory command line.

npm i -g create-react-app

After this, we can now create our react app with create-react-app (pun intended).

To do this, just type this in the command line.

create-react-app client && cd client

We will also need Axios in order to make get/post requests with ajax. So let’s install that now:

npm i -S axios

Wait for it to finish

then let’s proceed in organizing the front end so it will be easy to incorporate our back end later.

For PC users:

del src\App.css src\App.test.js src\index.css src\logo.svg\

For MAC users:

rm src/App.css src/App.test.js src/index.css src/logo.svg

Then, let’s edit our App.js file inside the client folder and let it just render something simple. We will further edit this file later on when we have our back end ready.

// client/src/App.js
import React, { Component } from "react"; class App extends Component {
render() {
return <div>I'M READY TO USE THE BACK END APIS! :-)</div>;
}
} export default App;

 We also have to edit our index.js and remove one line of code from there. We just have to remove the import ‘./index.css’; part of the code and we can now start our react app.

 

// client/src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

  

In order to start our front end, just type this in the command line.

npm start

and go to your browser and type http://localhost:3000/. You can now see that our front end is up and running.

Back It Up Just a Tad

Time to set-up our back end.

Go back to our main directory and let’s create our back end directory from there.

We will also initialize this directory so that we’ll have our package.json ready for building.

Your terminal will prompt you to enter some details for the package.json, just keep pressing enter until it is done.

mkdir backend && cd backend
npm init

Create a new file that will serve as our main code for the back end and name it server.js. Then, type the following into it.

This back end code is pretty blunt and basic, I have only created it so that beginners won’t have to think much of the complexity of the code rather than they would think about the code’s intent. Then, they could easy manipulate it afterwards once they wrapped their heads around it.

I’ve put comments beside every method for ease of understanding.

const mongoose = require('mongoose');
const express = require('express');
var cors = require('cors');
const bodyParser = require('body-parser');
const logger = require('morgan');
const Data = require('./data'); const API_PORT = 3001;
const app = express();
app.use(cors());
const router = express.Router(); // this is our MongoDB database
const dbRoute =
'mongodb://<your-db-username-here>:<your-db-password-here>@ds249583.mlab.com:49583/fullstack_app'; // connects our back end code with the database
mongoose.connect(dbRoute, { useNewUrlParser: true }); let db = mongoose.connection; db.once('open', () => console.log('connected to the database')); // checks if connection with the database is successful
db.on('error', console.error.bind(console, 'MongoDB connection error:')); // (optional) only made for logging and
// bodyParser, parses the request body to be a readable json format
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(logger('dev')); // this is our get method
// this method fetches all available data in our database
router.get('/getData', (req, res) => {
Data.find((err, data) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true, data: data });
});
}); // this is our update method
// this method overwrites existing data in our database
router.post('/updateData', (req, res) => {
const { id, update } = req.body;
Data.findByIdAndUpdate(id, update, (err) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true });
});
}); // this is our delete method
// this method removes existing data in our database
router.delete('/deleteData', (req, res) => {
const { id } = req.body;
Data.findByIdAndRemove(id, (err) => {
if (err) return res.send(err);
return res.json({ success: true });
});
}); // this is our create methid
// this method adds new data in our database
router.post('/putData', (req, res) => {
let data = new Data(); const { id, message } = req.body; if ((!id && id !== 0) || !message) {
return res.json({
success: false,
error: 'INVALID INPUTS',
});
}
data.message = message;
data.id = id;
data.save((err) => {
if (err) return res.json({ success: false, error: err });
return res.json({ success: true });
});
}); // append /api for our http requests
app.use('/api', router); // launch our backend into a port
app.listen(API_PORT, () => console.log(`LISTENING ON PORT ${API_PORT}`));

You might have noticed that a database link is already used in our back end code.

Don’t worry, that’s the next step in our article. Setting it up will also be as easy as the past few steps.

First, head on to MongoDB atlas and create an account there. MongoDB Atlas will let us use a free 500 MB of MongoDB database and use it remotely. It is also hosted in the cloud.

This is the current trend of our industry and acquiring skills that enables us to use cloud database is a real asset nowadays  

After setting up your account, log into your account.

Follow the steps prompted by the website in creating your own cluster and cluster/database users.

Here is the checklist or steps in order to create your own mongoDB database.

  1. Build your first cluster.
  2. Create your first database user.
  3. Whitelist your IP address (in our case, the localhost:3001)
  4. Connect your cluster.

We need to get the connection string of our database, so for step 4 we just need to click the connect button of our created cluster as shown below.

Then click “choose a connection method” at the bottom part of the modal, select “Connect your Application”. Then, copy the string show by the modal.

Paste this string uri in your server.js file. Find the dbRoute variable and put the link with your credentials there as a string.

Now, back to our back end source code.

We will now configure our database, in order to do so, create a file named data.js.

It should have the following code inside it.

// /backend/data.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema; // this will be our data base's data structure
const DataSchema = new Schema(
{
id: Number,
message: String
},
{ timestamps: true }
); // export the new Schema so we could modify it using Node.js
module.exports = mongoose.model("Data", DataSchema);

  

We are almost DONE! Let’s just install our back end’s package and modules and we are good to go.

Just pass this line on your command line.

npm i -S mongoose express body-parser morgan cors

Now, if we launch our back end using

node server.js

We can see in our console that it is ready and is listening on port 3001.

Let’s go back to our front end and start creating the UIs needed to dispatch actions unto our MongoDB + Node.JS + Express.JS system.

Go back to /client/src/App.js and apply the following changes.

// /client/App.js
import React, { Component } from 'react';
import axios from 'axios'; class App extends Component {
// initialize our state
state = {
data: [],
id: 0,
message: null,
intervalIsSet: false,
idToDelete: null,
idToUpdate: null,
objectToUpdate: null,
}; // when component mounts, first thing it does is fetch all existing data in our db
// then we incorporate a polling logic so that we can easily see if our db has
// changed and implement those changes into our UI
componentDidMount() {
this.getDataFromDb();
if (!this.state.intervalIsSet) {
let interval = setInterval(this.getDataFromDb, 1000);
this.setState({ intervalIsSet: interval });
}
} // never let a process live forever
// always kill a process everytime we are done using it
componentWillUnmount() {
if (this.state.intervalIsSet) {
clearInterval(this.state.intervalIsSet);
this.setState({ intervalIsSet: null });
}
} // just a note, here, in the front end, we use the id key of our data object
// in order to identify which we want to Update or delete.
// for our back end, we use the object id assigned by MongoDB to modify
// data base entries // our first get method that uses our backend api to
// fetch data from our data base
getDataFromDb = () => {
fetch('http://localhost:3001/api/getData')
.then((data) => data.json())
.then((res) => this.setState({ data: res.data }));
}; // our put method that uses our backend api
// to create new query into our data base
putDataToDB = (message) => {
let currentIds = this.state.data.map((data) => data.id);
let idToBeAdded = 0;
while (currentIds.includes(idToBeAdded)) {
++idToBeAdded;
} axios.post('http://localhost:3001/api/putData', {
id: idToBeAdded,
message: message,
});
}; // our delete method that uses our backend api
// to remove existing database information
deleteFromDB = (idTodelete) => {
parseInt(idTodelete);
let objIdToDelete = null;
this.state.data.forEach((dat) => {
if (dat.id == idTodelete) {
objIdToDelete = dat._id;
}
}); axios.delete('http://localhost:3001/api/deleteData', {
data: {
id: objIdToDelete,
},
});
}; // our update method that uses our backend api
// to overwrite existing data base information
updateDB = (idToUpdate, updateToApply) => {
let objIdToUpdate = null;
parseInt(idToUpdate);
this.state.data.forEach((dat) => {
if (dat.id == idToUpdate) {
objIdToUpdate = dat._id;
}
}); axios.post('http://localhost:3001/api/updateData', {
id: objIdToUpdate,
update: { message: updateToApply },
});
}; // here is our UI
// it is easy to understand their functions when you
// see them render into our screen
render() {
const { data } = this.state;
return (
<div>
<ul>
{data.length <= 0
? 'NO DB ENTRIES YET'
: data.map((dat) => (
<li style={{ padding: '10px' }} key={data.message}>
<span style={{ color: 'gray' }}> id: </span> {dat.id} <br />
<span style={{ color: 'gray' }}> data: </span>
{dat.message}
</li>
))}
</ul>
<div style={{ padding: '10px' }}>
<input
type="text"
onChange={(e) => this.setState({ message: e.target.value })}
placeholder="add something in the database"
style={{ width: '200px' }}
/>
<button onClick={() => this.putDataToDB(this.state.message)}>
ADD
</button>
</div>
<div style={{ padding: '10px' }}>
<input
type="text"
style={{ width: '200px' }}
onChange={(e) => this.setState({ idToDelete: e.target.value })}
placeholder="put id of item to delete here"
/>
<button onClick={() => this.deleteFromDB(this.state.idToDelete)}>
DELETE
</button>
</div>
<div style={{ padding: '10px' }}>
<input
type="text"
style={{ width: '200px' }}
onChange={(e) => this.setState({ idToUpdate: e.target.value })}
placeholder="id of item to update here"
/>
<input
type="text"
style={{ width: '200px' }}
onChange={(e) => this.setState({ updateToApply: e.target.value })}
placeholder="put new value of the item here"
/>
<button
onClick={() =>
this.updateDB(this.state.idToUpdate, this.state.updateToApply)
}
>
UPDATE
</button>
</div>
</div>
);
}
}

  

Lastly, we edit our front end’s package.json and add a proxy there to point to the port where our back end is deployed.

{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"react": "^16.5.0",
"react-dom": "^16.5.0",
"react-scripts": "1.1.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": "http://localhost:3001"
}

  Remember, this is our front end’s package.json so this is included inside the client directory. Edit that there.

There, all that’s left to do is to make it so that we can launch our back end then our front end at the same time.

In order to do that go back to the main directory of our project and type the following:

npm init -y
npm i -S concurrently

Edit the package.json of our main project’s directory. Change it as follows.

{
"name": "fullstack_app",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "concurrently \"cd backend && node server.js\" \"cd client && npm start\""
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"concurrently": "^4.0.1"
}
}

  Here, you can see under the “scripts” key, the “start” key makes use of the package we just installed, the concurrently package. That package enables us to run the back end code using:

node server.js

And the front end code using:

npm start

There’s a lot happening under the hood in able to do this, but for now, we will just leave it be and be happy that it works! Now, to start our app just go to the main directory of our project then type:

npm start

A browser will open that contains our app and voila! We have made our own MERN (FULL STACK) app from scratch! Feel free to play around with it. Use it as a sand box to grasp the different concepts of both ends here.

Oh, and one more thing. Make sure to enable CORS on your browser since we are calling our own APIs via our own machine. Here is a great plug-in to do just that

MERN——MongoDB && React && Node && Express的更多相关文章

  1. react + node + express + ant + mongodb 的简洁兼时尚的博客网站

    前言 此项目是用于构建博客网站的,由三部分组成,包含前台展示.管理后台和后端. 此项目是基于 react + node + express + ant + mongodb 的,项目已经开源,项目地址在 ...

  2. React+Node.js+Express+mongoskin+MongoDB

    首发:个人博客,更新&纠错&回复 采用React + Node.js + Express + mongoskin + MongoDB技术开发的一个示例,演示地址在这里,项目源码在这里. ...

  3. 基于react全家桶+antd-design+webpack2+node+express+mongodb开发的前后台博客系统

    很久没更新博客,最近也有点忙,然后业余时间搞了一个比较完整基于react全家桶+antd-design+webpack2+node+express+mongodb开发的前后台博客系统的流程系统,希望对 ...

  4. Webpact打包React后端Node+Express

    Webpact打包React后端Node+Express 前言 React官方推荐用Browserify或者Webpack 来开发React组件. Webpack 是什么?是德国开发者 Tobias ...

  5. Node+Express+MongoDB + Socket.io搭建实时聊天应用

    Node+Express+MongoDB + Socket.io搭建实时聊天应用 前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战 ...

  6. node+express+mongodb初体验

    从去年11月份到现在,一直想去学习nodejs,在这段时间体验了gulp.grunt.yeomen,fis,但是对于nodejs深入的去学习,去开发项目总是断断续续. 今天花了一天的时间,去了解整理整 ...

  7. Node+Express+MongoDB + Socket.io搭建实时聊天应用实战教程(二)--node解析与环境搭建

    前言 本来开始写博客的时候只是想写一下关于MongoDB的使用总结的,后来觉得还不如干脆写一个node项目实战教程实战.写教程一方面在自己写的过程中需要考虑更多的东西,另一方面希望能对node入门者有 ...

  8. Node+Express+MongoDB+Socket.io搭建实时聊天应用实战教程(一)--MongoDB入门

    前言 本文并不是网上流传的多少天学会MongoDB那种全面的教程,而意在总结这几天使用MongoDB的心得,给出一个完整的Node+Express+MongoDB+Socket.io搭建实时聊天应用实 ...

  9. Node操作MongoDB并与express结合实现图书管理系统

    Node操作MongoDB数据库 原文链接:http://www.xingxin.me/ Web应用离不开数据库的操作,我们将陆续了解Node操作MongoDB与MySQL这是两个具有代表性的数据库, ...

随机推荐

  1. 凤凰新闻APP的增长黑客流程步骤经验:3.5星|《我不是产品经理》

    “ 我问了他三个问题.●你是AI科学家或者算法工程师吗?答:不是.●你想天天坐在电脑旁点鼠标或者打电话吗?答:不想.●你愿意每天盯着数据仪表盘定策略并与生产者做运营沟通吗?答:不愿意.我回答他:你别去 ...

  2. canvas圆形进度条(逆时针)

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...

  3. 神经网络(3)---如何表示hypothesis,如何表示我们的model

    大脑中的神经元 我们的大脑都充满了上图所示的神经元,神经元有一个细胞体(cell body),还有一些input wires,专业词汇叫做树突(dendrite),它们从其它地方接收输入信息,神经元还 ...

  4. ***PHP preg_match正则表达式的使用 转载:https://www.cnblogs.com/kenshinobiy/p/4443600.html

    第一,让我们看看两个特别的字符:‘^’和‘$’他们是分别用来匹配字符串的开始和结束,以下分别举例说明 : "^The": 匹配以 "The"开头的字符串; &q ...

  5. 利用selenium自动化测试样例一

    import argparse import logging import psycopg2 import datetime,time import os,sys from selenium impo ...

  6. 【CSP模拟赛】God knows (李超线段树)

    题面 CODE 稍微分析一下,发现把(i,pi)(i,p_i)(i,pi​)看做二维数点,就是求极长上升子序列的权值最小值. 直接李超线段树 #include <bits/stdc++.h> ...

  7. 2.设计模式-Abstract Factory 抽象工厂模式

    大神勿喷,不对的地方请指出来,学笔记而已. 解决的问题:应对多系列对象构建的变化或多系列(例如:崎岖的山路和平坦的马路属于一个系列) 不断的变化的创建. 使用场景:对象不变(比如有3个对象 " ...

  8. 斐波那契数列 矩阵乘法优化DP

    斐波那契数列 矩阵乘法优化DP 求\(f(n) \%1000000007​\),\(n\le 10^{18}​\) 矩阵乘法:\(i\times k\)的矩阵\(A\)乘\(k\times j\)的矩 ...

  9. 常见的时间字符串与timestamp之间的转换 时间戳

    这里说的字符串不是一般意义上的字符串,是指在读取日期类型的数据时,如果还没有及时解析字符串,它就还不是日期类型,那么此时的字符串该怎么与时间戳之间进行转换呢? ① 时间字符串转化成时间戳 将时间字符串 ...

  10. 如何在微信小程序中国引入fontawesome字体图标

    fontawesome官网地址:http://fontawesome.dashgame.com/ 一. 二. 下载之后的字体图标 找到 文件中的如下图.ttf文件 三. 在https://transf ...