Crud Application using Mern Stack
By: Faiza Anan Noor
Tags: JavaScript, Reactjs, Mern Stack, Full Stack, Mongodb

After that let’s install the following things:

I’ll go over each of them as we stumble upon their use in our code.

Step 2:

Inside server.js

In server.js type in the above code.

Now let’s analyze what’s going on.

In line 1, we are including the module “express” by using the function require(). We installed this module in step 2 along with some other modules. So when we import the “express” module we basically get returned a function. Now let’s store that function in a constant variable called “express”.

Now let’s invoke the function “express” and then store that result in a constant variable called “app”. This app variable is actually an object. So in short, whenever this express function gets called we get an object and in our case we stored that object in a variable called “app”. Now we can use different functions of this object called app like app.use(), app.get(), app.listen()etc, more of which we will see later on.

At Line 3 we stored the result from importing the module “cors”. I’ll mention why we need this later on.

At Line 4, 5 we are importing the “dotenv” module and by calling the config() function we are basically making sure that we can pull or extract all our existing environment variables from our .env file.

At Line 8, we created a variable called Port, which will be equal to the environment variable called port if it has been initialized

OR

It will be set to the port 5000. You can set it to other ports if you want.

Now let’s use the app.listen() function to listen to the PORT 5000. And then let’s show the Line “Server running on port 5000” on our console.

That being done, our basic server has been created.

Now let’s place these two lines in the above way in our code.

The use() function is a way to register or use middleware or chain of middlewares before executing intermediary route logic depending upon order of middleware registration sequence.

Here cors and express.json are our middlewares.

CORS is a node.js package for providing an Express middleware that can be used to enable Cross-Origin Resource Sharing. Cross-origin requests are made using HTTP request methods. So inorder to enable these methods we need to enable CORS.

Express.json() allows us to send json objects in the body of our request during various http requests like POST,PUT etc.

Step 3: Connecting our Database

Follow this link to learn how you can configure the settings for mongoDb atlas and how you can use mongoDb compass. Now create a new database called “pokemons” and a collection called “pokemonData”.

Now we’re gonna create our schema and our model.

Create a .env dile and then place your copied mongodb uri for connecting to mongoDb via compass into that .env file. We won’t be keeping our .env file because of security issues. In server.js, we are going to establish a connection to mongoDb using this url from the .env file.

Explanation:

Here we are basically making a connection to our database using mongoose. mongoose.connect() takes in our mongo_uri from our .env file which we brought in earlier and then the second parameter takes in an object of some required parameters to support the connection to the newest version of mongoDb.

By doing all this we would to able to establish a connection, which will output the aforementioned line in the console only when a proper connection is established.

Create a Folder called “models” inside the backend folder and then create a file called “PokemonData.js”. In “PokemonData.js” we are gonna create our schema in the following way:

Inside PokemonData.js

Explanation:

Here we are just creating a schema by specifying our fields and the constraints for our fields too. Then we are registering or compiling a model for our schema by calling mongoose.model() on our schema. Then we’ll export it and then later on it will be imported in our server.js file right above our db connection.

inside server.js

Step 4: Designing our frontend:

Our frontend folder structure will look something like this:

Let’s now run the command “npm i react-router-dom” inside the client folder. This will enable us to create appropriate routes, links in our database.

Then let’s run the command “npm i axios”. Axios is a promise based http client. It can help us make HTTP requests to fetch or save data from the client side.

I’ve provided a minimalistic styling by providing the “bootstrap.min.css” so that you don’t have to worry too much about styling.

Let’s go over our App.js first,

import AddPokemon from './components/AddPokemon'; import EditPokemon from './components/EditPokemon'; import PokemonTable from './components/PokemonTable'; import Navbar from './layouts/Navbar'; import Axios from 'axios'; import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; import './App.css'; function App() { function addNewPokemon(Name, Type) { Axios.post('http://localhost:5000/insert', { Name: Name, Type: Type, }); alert('New Pokemon Added!'); } return ( <Router> <div className="App"> <Navbar></Navbar> <Route exact path="/" component={() => ( <AddPokemon addNewPokemon={addNewPokemon}></AddPokemon> )} ></Route> <Route exact path="/PokemonTable" component={PokemonTable}></Route> <Route path="/EditPokemon/:id/:name/:type" component={EditPokemon} ></Route> </div> </Router> ); } export default App;

Explanation:

Here we have created our routes for our components and have also passed in necessary functions and things as props by those components, to be used by child components.

In the addNewPokemonFunction(),we are sending a request to the server to input out values received by the AddPokemon.js component. Then those values get passed to the server and an insert operation is done.

We have also created routes for showing the EditPokemon View and the PokemonTable view.

In this code snippet,

<Route path="/EditPokemon/:id/:name/:type" component={EditPokemon} ></Route>

The “:id” portion of that route specifies that whatever you put into that position will be passed as the id in the params map.

The “:name” and “:type” portion of that route specifies that whatever you put into that position will be passed as the name and type in the params map.

So whenever a client side passes in the id, name, type in the EditPokemon.js file, the server can receive these values and perform functions accordingly.

In Navbar.js,

import React, { Component } from 'react'; import { Link } from 'react-router-dom'; export default class navbar extends Component { render() { return ( <div> <nav class="navbar navbar-expand-lg navbar-dark bg-primary"> <a class="navbar-brand" href="#"> POKEMON CRUD </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarColor01"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <Link to="/"> <a class="nav-link" href="#"> Home <span class="sr-only">(current)</span> </a> </Link> </li> <Link to="/PokemonTable"> <li class="nav-item"> <a class="nav-link" href="#"> Pokemon List </a> </li> </Link> </ul> </div> </nav> </div> ); } }

The output will look be something like this: