¿Cómo construir una aplicación CRUD básica con Node.js y ReactJS?

En este artículo, crearemos una aplicación básica para estudiantes desde cero.

Funcionalidad de la aplicación: 

  • Crear un nuevo estudiante
  • Actualizar un estudiante existente
  • Mostrar lista de estudiantes
  • Eliminar un estudiante

API REST en este proyecto: 

API REST 

URL

OBTENER http://localhost:4000/estudiantes
OBTENER /estudiantes/actualizar-estudiante/id
CORREO /estudiantes/crear-estudiante
PONER /estudiantes/actualizar-estudiante/id
ELIMINAR /estudiantes/eliminar-estudiante/id

En primer lugar, trabajaremos en la parte frontal de nuestra aplicación utilizando React.js.

Crear aplicación React e instalar módulos

Paso 1: Empecemos a construir la parte Front-end con React. Para crear una nueva aplicación React, ingrese el siguiente código en la terminal y presione enter. 

npx create-react-app mern-stack-crud

Paso 2: Vaya a la carpeta del proyecto React.

cd mern-stack-crud

Paso 3:  para ejecutar la aplicación React, ejecute el siguiente comando:

npm start

Este comando abre la aplicación React en el navegador en la siguiente URL: http://localhost:3000/

Paso 4:  Para construir la aplicación React, necesitamos instalar algunos módulos externos. 

MNP

Detalle

Reaccionar-Bootstrap React-Bootstrap ha evolucionado y crecido junto con React, lo que lo convierte en una excelente opción para su interfaz de usuario.
Reaccionar-Router-Dom React Router DOM le permite implementar enrutamiento en una aplicación React. 
Axios Es un cliente HTTP base de promesa y se usa para requests de red.
Formik Una gran biblioteca para construir formularios en React.
Sí, es un generador de esquemas de JavaScript para la validación de formularios.

Para instalar, ejecute el siguiente código en la terminal. 

npm i react-bootstrap@next bootstrap@5.1.0 react-router-dom axios formik sí

Paso 5: Creación de componentes simples de React: en este paso, crearemos algunos componentes de React para administrar los datos de los estudiantes.

Diríjase a la carpeta src , cree una carpeta y asígnele el nombre Componentes y dentro de ese directorio cree los siguientes componentes.

  • StudentForm.js – Formulario de estudiante reutilizable
  • create-student.component.js – Responsable de crear un nuevo estudiante 
  • edit-student.component.js – Responsable de actualizar los datos de los estudiantes
  • student-list.component.js – Responsable de mostrar todos los estudiantes
  • StudentTableRow.js  : responsable de mostrar un solo estudiante 

Estructura del proyecto: se verá así

estructura del proyecto front-end

Paso 6: Crear formulario de estudiante: en este paso, crearemos un formulario de estudiante reutilizable con Formik y React-Bootstrap. Este formulario tiene todos los campos necesarios para ingresar los detalles del estudiante. También hemos realizado la validación de formularios del lado del cliente con Yup. En el futuro, utilizaremos este componente para crear y actualizar un alumno. Vaya a src/Components/StudentForm.js y escriba el siguiente código. 

StudentForm.js

import React from "react";
import * as Yup from "yup";
import { Formik, Form, Field, ErrorMessage } from "formik";
import { FormGroup, FormControl, Button } from "react-bootstrap";
  
const StudentForm = (props) => {
  const validationSchema = Yup.object().shape({
    name: Yup.string().required("Required"),
    email: Yup.string()
      .email("You have enter an invalid email address")
      .required("Required"),
    rollno: Yup.number()
      .positive("Invalid roll number")
      .integer("Invalid roll number")
      .required("Required"),
  });
  console.log(props);
  return (
    <div className="form-wrapper">
      <Formik {...props} validationSchema={validationSchema}>
        <Form>
          <FormGroup>
            <Field name="name" type="text" 
                className="form-control" />
            <ErrorMessage
              name="name"
              className="d-block invalid-feedback"
              component="span"
            />
          </FormGroup>
          <FormGroup>
            <Field name="email" type="text" 
                className="form-control" />
            <ErrorMessage
              name="email"
              className="d-block invalid-feedback"
              component="span"
            />
          </FormGroup>
          <FormGroup>
            <Field name="rollno" type="number" 
                className="form-control" />
            <ErrorMessage
              name="rollno"
              className="d-block invalid-feedback"
              component="span"
            />
          </FormGroup>
          <Button variant="danger" size="lg" 
            block="block" type="submit">
            {props.children}
          </Button>
        </Form>
      </Formik>
    </div>
  );
};
  
export default StudentForm;

Paso 7: Crear un nuevo estudiante: En este paso, crearemos un componente para agregar un nuevo estudiante. Ya hemos creado un componente StudentForm para ingresar los detalles del estudiante. Ahora, es el momento de utilizar este componente. Vaya a src/Components/create-student.component.js y escriba el siguiente código.  

create-student.component.js

// CreateStudent Component for add new student
  
// Import Modules
import React, { useState, useEffect } from "react";
import axios from 'axios';
import StudentForm from "./StudentForm";
  
// CreateStudent Component
const CreateStudent = () => {
  const [formValues, setFormValues] = 
    useState({ name: '', email: '', rollno: '' })
  // onSubmit handler
  const onSubmit = studentObject => {
    axios.post(
'http://localhost:4000/students/create-student', 
    studentObject)
      .then(res => {
        if (res.status === 200)
          alert('Student successfully created')
        else
          Promise.reject()
      })
      .catch(err => alert('Something went wrong'))
  }
    
  // Return student form
  return(
    <StudentForm initialValues={formValues} 
      onSubmit={onSubmit} 
      enableReinitialize>
      Create Student
    </StudentForm>
  )
}
  
// Export CreateStudent Component
export default CreateStudent

Paso 8: Actualizar los detalles del estudiante: En esta sección, crearemos un componente para actualizar los detalles. Tenemos un componente StudentForm reutilizable , usémoslo de nuevo. Buscaremos los detalles del estudiante para reiniciar el formulario. Vaya a src/Components/edit-student.component.js y escriba el siguiente código.  

edit-student.component.js

// EditStudent Component for update student data
  
// Import Modules
import React, { useState, useEffect } from "react";
import axios from "axios";
import StudentForm from "./StudentForm";
  
// EditStudent Component
const EditStudent = (props) => {
  const [formValues, setFormValues] = useState({
    name: "",
    email: "",
    rollno: "",
  });
    
  //onSubmit handler
  const onSubmit = (studentObject) => {
    axios
      .put(
        "http://localhost:4000/students/update-student/" +
          props.match.params.id,
        studentObject
      )
      .then((res) => {
        if (res.status === 200) {
          alert("Student successfully updated");
          props.history.push("/student-list");
        } else Promise.reject();
      })
      .catch((err) => alert("Something went wrong"));
  };
  
  // Load data from server and reinitialize student form
  useEffect(() => {
    axios
      .get(
        "http://localhost:4000/students/update-student/" 
        + props.match.params.id
      )
      .then((res) => {
        const { name, email, rollno } = res.data;
        setFormValues({ name, email, rollno });
      })
      .catch((err) => console.log(err));
  }, []);
  
  // Return student form
  return (
    <StudentForm
      initialValues={formValues}
      onSubmit={onSubmit}
      enableReinitialize
    >
      Update Student
    </StudentForm>
  );
};
  
// Export EditStudent Component
export default EditStudent;

Paso 9: Mostrar la lista de estudiantes: En este paso, crearemos un componente para mostrar los detalles de los estudiantes en una tabla. Obtendremos los datos de los estudiantes y los repetiremos para crear una fila de tabla para cada estudiante. Vaya a src/Components/student-list.component.js y escriba el siguiente código.

student-list.component.js

import React, { useState, useEffect } from "react";
import axios from "axios";
import { Table } from "react-bootstrap";
import StudentTableRow from "./StudentTableRow";
  
const StudentList = () => {
  const [students, setStudents] = useState([]);
  
  useEffect(() => {
    axios
      .get("http://localhost:4000/students/")
      .then(({ data }) => {
        setStudents(data);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);
  
  const DataTable = () => {
    return students.map((res, i) => {
      return <StudentTableRow obj={res} key={i} />;
    });
  };
  
  return (
    <div className="table-wrapper">
      <Table striped bordered hover>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Roll No</th>
            <th>Action</th>
          </tr>
        </thead>
        <tbody>{DataTable()}</tbody>
      </Table>
    </div>
  );
};
  
export default StudentList;

Paso 10: Mostrar un solo estudiante: En este paso, devolveremos la fila de la tabla que es responsable de mostrar los datos de los estudiantes. Vaya a src/Components/StudentTableRow.js y escriba el siguiente código.

StudentTableRow.js

import React from "react";
import { Button } from "react-bootstrap";
import { Link } from "react-router-dom";
import axios from "axios";
  
const StudentTableRow = (props) => {
  const { _id, name, email, rollno } = props.obj;
  
  const deleteStudent = () => {
    axios
      .delete(
"http://localhost:4000/students/delete-student/" + _id)
      .then((res) => {
        if (res.status === 200) {
          alert("Student successfully deleted");
          window.location.reload();
        } else Promise.reject();
      })
      .catch((err) => alert("Something went wrong"));
  };
  
  return (
    <tr>
      <td>{name}</td>
      <td>{email}</td>
      <td>{rollno}</td>
      <td>
        <Link className="edit-link" 
          to={"/edit-student/" + _id}>
          Edit
        </Link>
        <Button onClick={deleteStudent} 
          size="sm" variant="danger">
          Delete
        </Button>
      </td>
    </tr>
  );
};
  
export default StudentTableRow;

Paso 11: Edite App.js: Finalmente, incluya el menú para hacer enrutamiento en nuestra aplicación MERN Stack CRUD. Vaya a src/App.js y escriba el siguiente código. 

App.js

// Import React
import React from "react";
  
// Import Bootstrap
import { Nav, Navbar, Container, Row, Col } 
        from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.css";
  
// Import Custom CSS
import "./App.css";
  
// Import from react-router-dom
import { BrowserRouter as Router, Switch,
    Route, Link } from "react-router-dom";
  
// Import other React Component
import CreateStudent from 
    "./Components/create-student.component";
import EditStudent from 
    "./Components/edit-student.component";
import StudentList from 
    "./Components/student-list.component";
  
// App Component
const App = () => {
  return (
    <Router>
      <div className="App">
        <header className="App-header">
          <Navbar bg="dark" variant="dark">
            <Container>
              <Navbar.Brand>
                <Link to={"/create-student"} 
                  className="nav-link">
                  React MERN Stack App
                </Link>
              </Navbar.Brand>
  
              <Nav className="justify-content-end">
                <Nav>
                  <Link to={"/create-student"} 
                    className="nav-link">
                    Create Student
                  </Link>
                </Nav>
  
                <Nav>
                  <Link to={"/student-list"} 
                    className="nav-link">
                    Student List
                  </Link>
                </Nav>
              </Nav>
            </Container>
          </Navbar>
        </header>
  
        <Container>
          <Row>
            <Col md={12}>
              <div className="wrapper">
                <Switch>
                  <Route exact path="/" 
                    component={CreateStudent} />
                  <Route path="/create-student" 
                    component={CreateStudent} />
                  <Route path="/edit-student/:id" 
                    component={EditStudent} />
                  <Route path="/student-list" 
                    component={StudentList} />
                </Switch>
              </div>
            </Col>
          </Row>
        </Container>
      </div>
    </Router>
  );
};
  
export default App;

Paso 12: Agregar estilo: vaya a src/App.css y escriba el siguiente código. 

App.css

.wrapper {
  padding-top: 30px;
}
  
body h3 {
  margin-bottom: 25px;
}
  
.navbar-brand a {
  color: #ffffff;
}
  
.form-wrapper,
.table-wrapper {
  max-width: 500px;
  margin: 0 auto;
}
  
.table-wrapper {
  max-width: 700px;
}
  
.edit-link {
  padding: 7px 10px;
  font-size: 0.875rem;
  line-height: normal;
  border-radius: 0.2rem;
  color: #fff;
  background-color: #28a745;
  border-color: #28a745;
  margin-right: 10px;
  position: relative;
  top: 1px;
}
  
.edit-link:hover {
  text-decoration: none;
  color: #ffffff;
}
  
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
  
/* Firefox */
input[type=number] {
  -moz-appearance: textfield;
}

Ahora, hemos creado con éxito la interfaz para nuestra mern-stack-app . Vamos a construir la parte de backend. Antes, saltando a la siguiente sección, observe cómo funciona la parte frontal sin backend.

Paso para ejecutar la aplicación: Abra la terminal y escriba el siguiente comando.

npm start

Producción:

Ahora trabajaremos en la parte de backend de nuestra aplicación. Crearemos una carpeta dentro de nuestro mern-stack-crud  para administrar los servicios del servidor, como la base de datos, los modelos, el esquema, las rutas y las API; nombre esta carpeta backend .

Paso 1: Ejecute el comando para crear una carpeta de back -end para el servidor y acceda a ella.

mkdir backend && cd backend

Paso 2: Crear package.json: a continuación, debemos crear un archivo package.json separado para administrar el servidor de nuestra aplicación mern-stack-crud  .

npm init -y

Vaya al archivo backend/package.json que tendrá el siguiente aspecto. Reemplace la propiedad de prueba como: 

"test": "echo \"Error: no test specified\" && exit 1" 
"start": "nodemon server.js"

Paso 3: Instalar dependencias de Nodes: instale las siguientes dependencias de Nodes. 

MNP

Detalle

Expresar Marco Node.js que ayuda a crear potentes API REST.
analizador de cuerpo Extrae la parte del cuerpo completo de un flujo de solicitud y lo expone en req.body.
corazones Es un paquete de Node.js que ayuda a habilitar el encabezado CORS Access-Control-Allow-Origin.
mangosta Es una base de datos NoSQL para crear una aplicación web robusta.

Para instalar las dependencias anteriores, ejecute el siguiente código en la terminal. 

npm install express body-parser cors mongoose

Puede instalar nodemon como dependencia de desarrollo para automatizar el proceso de reinicio del servidor.

npm i -D nodemon

Estructura del proyecto de back-end

estructura del proyecto back-end

Paso 4: Configuración de la base de datos MongoDB: en este paso, configuraremos una base de datos MongoDB para nuestra aplicación. Antes de comenzar, asegúrese de tener instalada la última versión de MongoDB en su sistema. Cree una carpeta dentro de la carpeta backend  y asígnele el nombre base de datos . Cree un archivo con el nombre de db.js dentro de la carpeta de la base de datos . Vaya a   backend/database/db.js y escriba el siguiente código. 

db.js

module.exports = {
  db: 'mongodb://localhost:27017/reactdb'
};

Hemos declarado la base de datos MongoDB y la hemos llamado reactdb

Paso 5: Defina el esquema Mongoose: ahora, cree el esquema MongoDB para interactuar con la base de datos MongoDB. Cree una carpeta llamada models dentro de la carpeta back -end para mantener los archivos relacionados con el esquema y cree un archivo Student.js dentro de ella para definir el esquema de MongoDB. Vaya a   backend/models/Student.js y escriba el siguiente código. 

Student.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
  
let studentSchema = new Schema({
  name: {
    type: String
  },
  email: {
    type: String
  },
  rollno: {
    type: Number
  }
}, {
    collection: 'students'
  })
  
module.exports = mongoose.model('Student', studentSchema)

Declaramos los campos de nombre, correo electrónico y rollno junto con sus respectivos tipos de datos en el esquema del estudiante.

Paso 6: Cree rutas usando ExpressJS: en este paso, configuramos algunas rutas (API REST) ​​para CREAR, LEER, ACTUALIZAR y ELIMINAR usando Express y Node.js. Estas rutas nos ayudarán a administrar los datos en nuestra aplicación mern-stack-crud . Cree una carpeta y asígnele el nombre rutas dentro de la carpeta backend. Aquí guardaremos todos los archivos relacionados con las rutas. Además, cree un archivo y asígnele el nombre student.routes.js dentro de la carpeta de rutas , en este archivo definiremos nuestras rutas. 

mkdir routes && cd routes && touch student.route.js

Luego, vaya al archivo backend/routes/student.route.js y escriba el siguiente código. 

student.route.js

let mongoose = require("mongoose"),
  express = require("express"),
  router = express.Router();
  
// Student Model
let studentSchema = require("../models/Student");
  
// CREATE Student
router.post("/create-student", (req, res, next) => {
  studentSchema.create(req.body, (error, data) => {
    if (error) {
      return next(error);
    } else {
      console.log(data);
      res.json(data);
    }
  });
});
  
// READ Students
router.get("/", (req, res) => {
  studentSchema.find((error, data) => {
    if (error) {
      return next(error);
    } else {
      res.json(data);
    }
  });
});
  
// UPDATE student
router
  .route("/update-student/:id")
  // Get Single Student
  .get((req, res) => {
    studentSchema.findById(
        req.params.id, (error, data) => {
      if (error) {
        return next(error);
      } else {
        res.json(data);
      }
    });
  })
  
  // Update Student Data
  .put((req, res, next) => {
    studentSchema.findByIdAndUpdate(
      req.params.id,
      {
        $set: req.body,
      },
      (error, data) => {
        if (error) {
          return next(error);
          console.log(error);
        } else {
          res.json(data);
          console.log("Student updated successfully !");
        }
      }
    );
  });
  
// Delete Student
router.delete("/delete-student/:id", 
(req, res, next) => {
  studentSchema.findByIdAndRemove(
      req.params.id, (error, data) => {
    if (error) {
      return next(error);
    } else {
      res.status(200).json({
        msg: data,
      });
    }
  });
});
  
module.exports = router;

Paso 7: Configure server.js: casi hemos creado todo para nuestra aplicación mern-stack-crud . Ahora, cree el archivo server.js en la raíz de la carpeta backend . Vaya a backend/server.js y escriba el siguiente código.

server.js

let express = require('express');
let mongoose = require('mongoose');
let cors = require('cors');
let bodyParser = require('body-parser');
let dbConfig = require('./database/db');
  
// Express Route
const studentRoute = require('../backend/routes/student.route')
  
// Configure mongoDB Database
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('useUnifiedTopology', true);
  
// Connecting MongoDB Database
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db).then(() => {
  console.log('Database successfully connected!')
},
  error => {
    console.log('Could not connect to database : ' + error)
  }
)
  
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(cors());
app.use('/students', studentRoute)
  
  
// PORT
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
  console.log('Connected to port ' + port)
})
  
// 404 Error
app.use((req, res, next) => {
  res.status(404).send('Error 404!')
});
  
app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
});

Ahora, hemos creado con éxito el backend para nuestra mern-stack-app .  

Nuestra estructura final de directorios del proyecto:

proyecto-directorio-estructura

Ahora, inicie el servidor de base de datos MongoDB para ejecutar el servidor.

Paso para ejecutar la aplicación: abra una terminal y ejecute el siguiente comando para iniciar el servidor Nodemon permaneciendo en la carpeta backend .

npm start

Si todo funciona bien, verá el siguiente resultado en la pantalla del terminal. 

mern-stack-crud servidor-ejecutando

resultado final: 

aplicación mern-stack-crud

Publicación traducida automáticamente

Artículo escrito por braktim99 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *