visit
Note: The goal of this tutorial is to provide you with a high-level overview of what it's like to build a full stack application, rather than a detailed explanation of MERN stack technologies.
We know what we need to do; now let's figure out how to do it.
npx create-react-app client
.
├── README.md
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ ├── logo192.png
│ ├── logo512.png
│ ├── manifest.json
│ └── robots.txt
└── src
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js
├── logo.svg
├── reportWebVitals.js
└── setupTests.js
For the time being, we are only interested in the App.js
and App.css
files.
Remove all existing code from the App.js
and App.css
files.
Let's make a react component.
Add the App component to the App.js
file.
import "./App.css";
const App = () => {
return <div>My App</div>;
}
export default App;
The above code creates and renders the App component.
npm start
Design the app.
...
<div className="app">
<header className="app-header">
<h1>Productivity Tracker</h1>
<form>
<div>
<label htmlFor="activity">Activity:</label>
<input
type="text"
id="activity"
name="activity"
autoComplete="off"
/>
</div>
<div>
<label htmlFor="time">Time Taken:</label>
<input type="text" id="time" name="time" autoComplete="off" />
</div>
<button type="submit">Add</button>
</form>
</header>
<main className="app-main">
<h2>Today</h2>
<ol>
<li> Activity 1 - 3 hours</li>
<li> Activity 2 - 10 min</li>
<li> Activity 3 - 2 hours and 25 min</li>
</ol>
</main>
</div>
...
App.css
file.Add logic.
...
const [activities, setActivities] = useState([]);
...
...
<main className="app-main">
<h2>Today</h2>
{activities && activities.length > 0 ? (
<ol>
{activities.map((activity) => (
<li key={activity._id}>
{activity.name} - {activity.time}
</li>
))}
</ol>
) : (
<p>No activities yet</p>
)}
</main>
...
mongodb+srv://<username>:<password>@<clusterUrl>/<databaseName>?retryWrites=true&w=majority
In the terminal, open the folder and type npm init
. Fill in all the details.
npm i express mongoose dotenv
Make a .env
file and save your connection string in a variable called "MongoDB URI".
MONGODB_URI=yourconnectionstring
Create a server.js
file and paste this code.
const express = require("express");
const mongoose = require("mongoose");
const app = express();
/* Loading the environment variables from the .env file. */
require("dotenv").config();
const PORT = process.env.PORT || 5000;
const MONGODB_URI = process.env.MONGODB_URI || "mongodb://localhost/todoapiDB";
/* Telling the application to use the express.json() middleware. This middleware will parse the body of
any request that has a Content-Type of application/json. */
app.use(express.json());
/* This is a route handler. It is listening for a GET request to the root route of the application.
When it receives a request, it will send back a response with the string "Hello World!". */
app.get("/", (req, res) => {
res.send("Hello World!");
});
/* Connecting to the database and then starting the server. */
mongoose
.connect(MONGODB_URI, { useNewUrlParser: true })
.then(() => {
app.listen(PORT, console.log("Server stated on port 5000"));
})
.catch((err) => {
console.log(err);
});
Run the below command and go to in your browser. You will see something like this. (Make sure you have installed globally.)
npm run dev
This means the server is running successfully.
Create a folder called "models" and in that folder create a file activity.model.js
. Copy and paste the below code.
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
/* Creating a new schema for the activity model. */
const activitySchema = new Schema({
name: {
type: String,
required: true,
},
time: {
type: String,
required: true,
},
});
module.exports = mongoose.model("Activity", activitySchema);
Create a folder called "controllers" and in that folder create a file activity.controller.js
.
const Activity = require("../models/activity.model");
/**
* It's an async function that uses the Activity model to find all activities and then returns a status of 200 with the activities in the response body.
*/
const getActivities = async (req, res) => {
try {
const activities = await Activity.find();
res.status(200).json(activities);
} catch (err) {
res.status(500).json({ message: err.message });
}
};
/**
* It creates a new activity and saves it to the database.
*/
const addActivity = async (req, res) => {
const activity = new Activity(req.body);
try {
const newActivity = await activity.save();
res.status(201).json(newActivity);
} catch (err) {
res.status(400).json({ message: err.message });
}
};
module.exports = {
getActivities,
addActivity,
};
Create a folder called "routes" and in that folder create a file activity.route.js
. Copy and paste the below code.
const express = require("express");
const {
getActivities,
addActivity,
} = require("../controllers/activity.controller");
const router = express.Router();
/* Creating a route for the get request. */
router.get("/activities", getActivities);
/* Creating a route for the post request. */
router.post("/activity", addActivity);
module.exports = router;
.
├── controllers
│ └── activity.controller.js
├── models
│ └── activity.model.js
├── routes
│ └── activity.route.js
├── package-lock.json
├── package.json
└── server.js
Open the server.js
file and use the registered routes.
...
const ActivityRouter = require("./routes/activity.route");
...
...
/* Telling the application to use the ActivityRouter for any requests that start with "/api". */
app.use("/api", ActivityRouter);
...
Navigate to the client folder and create a .env.local
file. Paste the backend URL into a variable.
REACT_APP_BACKEND_URL=//localhost:5000/api
Navigate to the client folder and open App.js
. When the user clicks the Add button, we must make a POST request to the server via the /api/activity
route.
Create a function called handleSubmit()
and add the onSubmit
attribute to the form element.
...
const addActivity = async (event) => {
event.preventDefault();
const newActivity = {
name: event.target.activity.value,
time: event.target.time.value,
};
await fetch(`${process.env.REACT_APP_BACKEND_URL}/activity`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(newActivity),
});
event.target.activity.value = ""; // sets input empty after clicking submit
event.target.time.value = ""; // sets input empty after clicking submit
window.location.reload(); // reloads the window after sending request
};
...
...
<form onSubmit={addActivity}>
...
Enter an activity name and time, then submit. (Ensure that the server is also up and running.)
npm i cors
Then use this package in server.js
.
...
const cors = require("cors");
...
...
/* Allowing the frontend to access the backend. */
app.use(cors());
...
We must display activities as soon as the component renders. We can accomplish this by using useEffect()
a hook. Fetch the data from the server and save it to the state.
...
/* Fetching the data from the backend and setting the state of activities to the data. */
useEffect(() => {
const fetchData = async () => {
const result = await fetch(
`${process.env.REACT_APP_BACKEND_URL}/activities`
);
const data = await result.json();
setActivities(data);
};
fetchData();
}, []);
...
.gitignore
file and paste the following stuff.node_modules
.env
npm run build
REACT_APP_BACKEND_URL
and the previously copied backend URL in the value field. Put /api
at the end of the URL.
Also Published