First Full Stack MERN/ JS Application
Startup Notes:
run in terminal:
npm init -y
npm install express
npm install mongoose
Add to Server.js file:
const express = require('express')
const app = express()
const port = 8000
app.listen(port, () => console.log(
Listening on port: ${port}))
Create 4 folders:
Config
Controllers
Models
Routes
Navigate to main folder
cd ..
Create React App
npm create-react-app client
Navigate to Controller Folder
Create Controller File ( Ex: person.controller.js )
Add Code/Setup:
`module.exports.index = (request,response) =>{ //Exporting a key:val pair of index:function
response.json({ // this is where we're setting the API's response to the requesting client
message:"hello world"
})
}`
Navigate to Routes Folder
Create Route File ( Ex: person.routes.js )
Add Code/Setup:
`const PersonController = require('../controllers/person.controller') // Here we are importing logic from controller file
module.exports = (app) =>{
app.get('/api', PersonController.index)
}`
Link Routes To Server.js
require('./routes/person.routes')(app)
// These two lines are the long-hand notation of the code above. They better show what's going on.
// const personRoutes = require("./routes/person.routes"); <-- assign the exported function to a const
// personRoutes(app); <-- invoke the function and pass in the express "app" server
Navigate To Client Folder In Terminal
cd client
Import Axios
npm install axios
Create COMPONENTS Folder ( Client -> SRC -> Components )
Create Components For Application
Example Person Component:
`import React, { useEffect, useState } from 'react'
import axios from 'axios';
const PersonForm= () => {
const [ message, setMessage ] = useState("Loading...")
useEffect(()=>{
axios.get("http://localhost:8000/api")
.then(res=>setMessage(res.data.message))
.catch(err=>console.log(err))
}, []);
return (
<div>
<h2>Message from the backend: {message}</h2>
</div>
)
}
export default PersonForm;`
Navigate To App.Js and IMPORT the components
Example:
`import React from 'react';
import PersonForm from './components/PersonForm';
function App() {
return (
<div className="App">
<PersonForm/>
</div>
);
}
export default App;`
START BACK-END SERVER
cd server folder
nodemon server.js
START FRONT-END REACT APP
OPEN new terminal
cd client
npm run start
Install the ability to make cross-origin requests
stop the nodemon server.js server with CONTROL C
run:
npm install cors
add needed CORS code to SERVER.JS
const cors = require('cors')
app.use(cors())
run: nodemon server.js
Update Back-End
we need to configure the database
Navigate to the Config Folder
Create: mongoose.config.js
Add to mongoose.config.js file
const mongoose = require('mongoose');
//This will create a database named "person" if one doesn't already exist (no need for mongo shell!):
mongoose.connect("mongodb://localhost/person", {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("Established a connection to the database"))
.catch(err => console.log("Something went wrong when connecting to the database", err));
Create Model File
Create Schema / Model
Example:
const mongoose = require('mongoose')
const PersonSchema = new mongoose.Schema({
firstName: {type: String},
lastName: {type: String}
},
{timestamps: true})
module.exports = mongoose.model('Person', PersonSchema)
Now in the controller we can add a new method to handle the creation of Person
server/controller/person.controller.js file
Add:
const Person = require('../models/person.model')
module.exports.createPerson = (request, response) => {
// Mongoose's "create" method is run using our Person model to add a new person to our db's person collection.
// request.body will contain something like {firstName: "Billy", lastName: "Washington"} from the client
Person.create(request.body) //This will use whatever the body of the client's request sends over
.then(person => response.json(person))
.catch(err => response.json(err));
}
Update the routes
server/routes/person.routes.js
Add:
app.post('/api/people', PersonController.createPerson)
In order to process POST requests add code to Server.js File
server/server.js
app.use(express.json())
this allows json objects to be posted
app.use(express.urlencoded({ extended: true}))
this allows json objects with strings and arrays
require(./config/mongoose.config')
this imports the config file
Now Navigate to POSTMAN
From here we can input data
Settings:
POST localhost:8000/api/__________
Click : BODY
Change DROPDOWN : x-www-form-urlencoded
Add KEYS and VALUES according to the schema created in the MODEL file.
Confirm BACK-END works !
UPDATE FRONT-END
Navigate to COMPONENTS Folder
Create a form to provide info to the back end
Example:
import React, { useState } from 'react'
import axios from 'axios';
const PersonForm = () => {
//keep track of what is being typed via useState hook
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
//handler when the form is submitted
const onSubmitHandler = (e) => {
//prevent default behavior of the submit
e.preventDefault();
//make a post request to create a new person
axios.post('http://localhost:8000/api/people', {
firstName, // this is shortcut syntax for firstName: firstName,
lastName // this is shortcut syntax for lastName: lastName
})
.then(res=>{
console.log(res); // always console log to get used to tracking your data!
console.log(res.data);
})
.catch(err=>console.log(err))
}
return (
<form onSubmit={onSubmitHandler}>
<p>
<label>First Name</label><br/>
{/* When the user types in this input, our onChange synthetic event
runs this arrow function, setting that event's target's (input)
value (what's typed into the input) to our updated state */}
<input type="text" onChange = {(e)=>setFirstName(e.target.value)}/>
</p>
<p>
<label>Last Name</label><br/>
<input type="text" onChange = {(e)=>setLastName(e.target.value)}/>
</p>
<input type="submit"/>
</form>
)
}
export default PersonForm;`