Creeu una aplicació CRUD senzilla amb React i Node

react and node

Taula de continguts

En aquest article, aprendrem a crear una aplicació CRUD senzilla amb React.js, Node.js i TailwindCSS.

Què és una aplicació CRUD?

Una aplicació CRUD realitza quatre operacions bàsiques d’aplicacions, a saber, crear , llegir , actualitzar i eliminar . Moltes aplicacions amb les quals interactueu diàriament realitzen aquestes tasques bàsiques. Prenguem Instagram com a exemple. Podeu crear perfils i publicacions emmagatzemades a la base de dades, llegir els vostres perfils i publicacions i els d’altres usuaris. Aquests detalls es recuperen de les dades creades emmagatzemades. També podeu actualitzar i suprimir les vostres publicacions, imatges de perfil, etc.

També us pot interessar: “Integració de PayPal Checkout amb React”

A part de requerir un front-end i un servidor, aquestes funcions requereixen una base de dades com MongoDB per emmagatzemar, recuperar, actualitzar i eliminar les dades enviades per l’usuari. Com us podeu imaginar, la configuració requereix molt d’esforç, per això ens vam alegrar quan vam descobrir una senzilla API REST falsa que podem utilitzar per realitzar tasques CRUD bàsiques per a la nostra aplicació.

Objectiu

El nostre objectiu avui és aprendre les tasques següents:

  • Instal·lar paquets bàsics amb Node.js
  • Crear una interfície d’usuari excel·lent amb React i Tailwind CSS
  • Realitzar operacions CRUD bàsiques amb la nostra aplicació.

Requisits previs

  • Coneixements de React js i React Hooks.
  • React 16.8 o posterior

Crea una aplicació React

Comencem a utilitzar el boilerplate de React CRA per crear la nostra aplicació React. Com que utilitzarem Tailwind CSS, seguirem els passos de la documentació oficial per fer que la instal·lació sigui perfecta.

Començar amb,

npx create-react-app my-react-crudapp
cd my-react-crudapp

Obriu la carpeta del vostre IDE preferit i completeu la resta de passos. A continuació, hem d’instal·lar React Router DOM , una funcionalitat d’encaminament que ens ajuda a navegar per la nostra aplicació.

npm install react-router-dom

Executeu, inicieu l’execució npm i hauríeu d’obtenir la popular pàgina de Benvinguda React tal com es mostra a continuació.

Aplicació React

Primer, crearem el nostre component de navegació. Per fer-ho, utilitzarem tant com sigui possible components de la pàgina de documentació de Tailwind.

Creeu un component Naviagte.js a la vostra carpeta src.

import React from "react";
export default function Navigate(){
   return (
       <nav class="flex items-center justify-between flex-wrap bg-green-500 p-6">
           <div class="flex items-center flex-shrink-0 text-white mr-6">
               <span class="font-semibold text-xl tracking-tight">REACT CRUD APP</span>
           </div>          
           <div>
               <button class="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-green-500 hover:bg-white mt-4 lg:mt-0">
                   CREATE
               </button>
           </div>
       </nav>
   )
}

A continuació, trucarem al react-router-dom i al nostre Navigate.js al Component principal App.js.

import { Link } from "react-router-dom";
export default function Navigate(){
   return (
       <nav class="flex items-center justify-between flex-wrap bg-green-500 p-6">
       <div class="flex items-center flex-shrink-0 text-white mr-6">
           <span class="font-semibold text-xl tracking-tight">REACT CRUD APP</span>
       </div>
       <Link to="/">
           <button class="inline-block text-sm px-4 py-2 leading-none border rounded text-white border-white hover:border-transparent hover:text-green-500 hover:bg-white mt-4 lg:mt-0">
               HOME
           </button>
       </Link>
       </nav>
   )
}
Aplicació React CRUD

OPERACIONS CRUD

És hora de començar a construir les nostres funcionalitats CRUD. Aquestes són les trucades a l’API que farem per aconseguir-ho.

API de l'aplicació React CRUD

Primer, creem un UsersList.js que ens ajudi a llegir els usuaris existents que ja proporciona l’API per a la prova. Un cop més, serem un component d’IU oficial per crear aquest .

UsersList.js

import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
 
function UsersList() {
   const [users, setUsers] = useState([]);
   useEffect(() => {
       ReadUsers()
   }, [])
 
   const ReadUsers = () => {
       fetch("https://www.mecallapi.com/api/users")
         .then(res => res.json())
         .then(
           (result) => {
             setUsers(result)
           }
         )
   }
   return (
       <div class="flex flex-col">
           <div class="-my-2 overflow-x-auto">
               <div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
                   <div class="lg:flex lg:items-center lg:justify-between px-20 py-2">
                       <div class="flex-1 min-w-0">
                           <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:text-3xl sm:truncate">
                           Users List
                           </h2>
                       </div>
                       <div class="mt-5 flex lg:mt-0 lg:ml-4">
                           <span class="hidden sm:block">
                           <Link to="/create">
                               <button type="button" class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                                   <svg class="-ml-1 mr-2 h-5 w-5 text-gray-500"  viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
                                   <path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
                                   </svg>
                                   CREATE
                               </button>
                           </Link>
                           </span>
                       </div>
                   </div>
               <div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
                   <table class="min-w-full divide-y divide-gray-200">
                   <thead class="bg-gray-50">
                       <tr>
                       <th scope="col" class="px-10 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                           ID
                       </th>
                       <th scope="col" class="px-10 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                           Full Name
                       </th>
                       <th scope="col" class="px-6 py-1 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                           Email Address
                       </th>
                      
                       <th scope="col" class="relative px-6 py-1">
                           <span class="sr-only">Edit</span>
                       </th>
                       </tr>
                   </thead>
                   <tbody class="bg-white divide-y divide-gray-200">
                   {users.map((user) => (
                       <tr key={user.ID}>
                           <td class="px-10 py-4 whitespace-nowrap">
                               <div class="text-sm text-gray-500">
                                   {user.id}
                               </div>
                           </td>
                           <td class="px-6 py-4 whitespace-nowrap">
                               <div class="flex items-center">
                               <div class="flex-shrink-0 h-10 w-10">
                                   <img class="h-10 w-10 rounded-full" src={user.avatar} alt=" />
                               </div>
                               <div class="ml-4">
                                   <div class="text-sm font-medium text-gray-900">
                                  <span> {user.fname}</span> <span>{user.lname}</span>
                                   </div>
                               </div>
                               </div>
                           </td>
                           <td class="px-6 py-4 whitespace-nowrap">
                               <div class="text-sm text-gray-500">
                                   {user.username}
                               </div>
                           </td>
                           <td class="px-6 py-4 space-x-2 whitespace-nowrap text-right text-sm font-medium">
                               <button class="inline-block text-sm px-4 py-2 leading-none border rounded text-blue-800 border-blue-600 hover:bg-blue-300 hover:text-blue-500 mt-4 lg:mt-0">EDIT</button>
                               <button class="inline-block text-sm px-4 py-2 leading-none border rounded text-red-800 border-red-600 hover:bg-red-300 hover:text-red-500 mt-4 lg:mt-0">DELETE</button>
                           </td>
                       </tr>
                       ))}
                   </tbody>
                   </table>
               </div>
               </div>
           </div>
       </div>
   )
}
 
export default UsersList;

Al bloc de codi anterior, hem utilitzat React useEffect Hook per obtenir la llista d’usuaris un cop carregada. Després d’això, vam emmagatzemar les dades rebudes mitjançant un useState Hook i les vam assignar als components de la taula proporcionats per Tailwind CSS. A les seccions següents, farem servir el botó Edita i Elimina i Crea que hem creat.

Aplicació React CRUD

CreateUser.js

A continuació, crearem CreateUser.js que ens permetrà crear un usuari.

import React, { useState } from "react";
 
function CreateUser() {
  
   const handleSubmit = event => {
     event.preventDefault();
     var data = {
       'fname': fname,
       'lname': lname,
       'username': username,
       'email': email,
       'avatar': avatar,
     }
 
     fetch('https://www.mecallapi.com/api/users/create', {
       method: 'POST',
       headers: {
         Accept: 'application/form-data',
         'Content-Type': 'application/json',
       },
       body: JSON.stringify(data),
     })
     .then(res => res.json())
     .then(
       (result) => {
         alert(result['message'])
         if (result['status'] === 'ok') {
           window.location.href = '/';
         }
       }
     )
   }
    const [fname, setFname] = useState('');
   const [lname, setLname] = useState('');
   const [username, setUsername] = useState('');
   const [email, setEmail] = useState('');
   const [avatar, setAvatar] = useState('');
 
   return (
       <form class="w-full max-w-lg mx-auto my-20" onSubmit={handleSubmit}>
       <div class="flex flex-wrap mx-3 mb-2">
           <div class="w-full md:w-1/2 px-3 mb-3 md:mb-0">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
               First Name
           </label>
           <input
           class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name"
           type="text"
           placeholder="First Name"
           onChange={(e) => setFname(e.target.value)}
           label="First Name"
           />
              
          
           </div>
           <div class="w-full md:w-1/2 px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
           for="grid-last-name">
               Last Name
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name"
           type="text" placeholder="Last Name"
           onChange={(e) => setLname(e.target.value)}
           label="Last Name"
           />
           </div>
       </div>
       <div class="flex flex-wrap mx-3 mb-2">
           <div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
               <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
                   Email Address
               </label>
               <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name"
               type="email"  placeholder="Email address"
               onChange={(e) => setEmail(e.target.value)}
               label="Email"
               />
           </div>
           <div class="w-full md:w-1/2 px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-last-name">
               Username
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name"
           label="Username"
           onChange={(e) => setUsername(e.target.value)}
           type="text" placeholder="janeDoe"
           />
           </div>
       </div>
       <div class="flex flex-wrap mx-3 mb-1">
           <div class="w-full px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-image">
               Avatar
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-image" type="text"
           placeholder="Image link"
           label="Avatar"
           onChange={(e) => setAvatar(e.target.value)}
           />
           </div>
       </div>
       <button type="submit" class="inline-flex items-center ml-8 px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
           SUBMIT
       </button>
      
       </form>
   )
}
 
export default CreateUser;

Al bloc de codi anterior, vam crear un formulari i vam afegir els seus valors d’entrada a les variables d’estat corresponents mitjançant el ganxo UseState. Després vam enviar aquests valors a l’API CRUD REST per crear un usuari.

També importarem i utilitzarem el nou component creat al nostre App.js:

import CreateUser from './CreateUser'
………………….
<Route path='/create' element={<CreateUser />} />
Crear pàgina

UpdateUser.js

El següent pas és crear un component UpdateUser.js que ens permetrà editar correctament els usuaris creats.

Primer, crearem una funció updateUser a UsersLists.js

const UpdateUser = id => {
   window.location = '/update/'+id
 }

i passa-ho al botó d’edició.

onClick={() => UpdateUser(user.id)}

Ara, podem crear el nostre UpdateUser.js

import React, { useState, useEffect } from "react";
import { useParams } from 'react-router-dom';
 
function UpdateUser() {
    const { id } = useParams();
 
   useEffect(() => {
     fetch("https://www.mecallapi.com/api/users/"+id)
       .then(res => res.json())
       .then(
         (result) => {
           setFname(result.user.fname)
           setLname(result.user.lname)
           setUsername(result.user.username)
           setEmail(result.user.email)
           setAvatar(result.user.avatar)
         }
       )
   }, [id])
    const handleSubmit = event => {
     event.preventDefault();
     var data = {
       'id': id,
       'fname': fname,
       'lname': lname,
       'username': username,
       'email': email,
       'avatar': avatar,
     }
     fetch('https://www.mecallapi.com/api/users/update', {
       method: 'PUT',
       headers: {
         Accept: 'application/form-data',
         'Content-Type': 'application/json',
       },
       body: JSON.stringify(data),
     })
     .then(res => res.json())
     .then(
       (result) => {
         alert(result['message'])
         if (result['status'] === 'ok') {
           window.location.href = '/';
         }
       }
     )
   }
    const [fname, setFname] = useState('');
   const [lname, setLname] = useState('');
   const [username, setUsername] = useState('');
   const [email, setEmail] = useState('');
   const [avatar, setAvatar] = useState('');
    return (
       <form class="w-full max-w-lg mx-auto my-20" onSubmit={handleSubmit}>
       <div class="flex flex-wrap mx-3 mb-2">
           <div class="w-full md:w-1/2 px-3 mb-3 md:mb-0">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
               First Name
           </label>
           <input
           class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name"
           type="text"
           value={fname}
           onChange={(e) => setFname(e.target.value)}
           label="First Name"
           />
              
          
           </div>
           <div class="w-full md:w-1/2 px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"
           for="grid-last-name">
               Last Name
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name"
           type="text" value={lname}
           onChange={(e) => setLname(e.target.value)}
           label="Last Name"
           />
           </div>
       </div>
       <div class="flex flex-wrap mx-3 mb-2">
           <div class="w-full md:w-1/2 px-3 mb-6 md:mb-0">
               <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-first-name">
                   Email Address
               </label>
               <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" id="grid-first-name"
               type="email"  value={email}
               onChange={(e) => setEmail(e.target.value)}
               label="Email"
               />
           </div>
           <div class="w-full md:w-1/2 px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-last-name">
               Username
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-last-name"
           label="Username"
           onChange={(e) => setUsername(e.target.value)}
           type="text" value={username}
           />
           </div>
       </div>
       <div class="flex flex-wrap mx-3 mb-1">
           <div class="w-full px-3">
           <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-image">
               Avatar
           </label>
           <input class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" id="grid-image" type="text"
           value={avatar}
           label="Avatar"
           onChange={(e) => setAvatar(e.target.value)}
           />
           </div>
       </div>
       <button type="submit" class="inline-flex items-center ml-8 px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
           Update
       </button>
      
       </form>
   )
}
 
export default UpdateUser;

Al fragment de codi anterior, hem recuperat i mostrat l’identificador d’usuari actual de l’usuari que voldríem editar-ne els detalls. A continuació, hem actualitzat els valors mitjançant les entrades del formulari fetes per l’usuari.

També importarem i utilitzarem el nou component creat al nostre App.js:

import UpdateUser from './UpdateUser'
………
<Route path='/update/:id' element={<UpdateUser />}/>
Pàgina d'actualització

ELIMINAR

Finalment, activarem el botó d’eliminació. Això no requereix cap component nou, actualitzarem el nostre component UsersList.js.

const DeleteUser = id => {
       var data = {
         'id': id
       }
       fetch('https://www.mecallapi.com/api/users/delete', {
         method: 'DELETE',
         headers: {
           Accept: 'application/form-data',
           'Content-Type': 'application/json',
         },
         body: JSON.stringify(data),
       })
       .then(res => res.json())
       .then(
         (result) => {
           alert(result['message'])
           if (result['status'] === 'ok') {
               ReadUsers()
           }
         }
       )
     }

<button onClick={() => DeleteUser(user.id)} class="inline-block text-sm px-4 py-2 leading-none border rounded text-red-800 border-red-600 hover:bg-red-300 hover:text-red-500 mt-4 lg:mt-0">DELETE</button>

Demostració

Resum

Això és tot per ara. En conclusió, aprenem a utilitzar Node.js per instal·lar paquets essencials per al nostre React. A continuació, hem utilitzat React Hooks i React Router per crear i navegar pels nostres components. Finalment, hem fet interaccions CRUD bàsiques per crear, llegir, actualitzar i eliminar els detalls dels usuaris.

Si esteu interessats a desenvolupar encara més les vostres habilitats React i Node js, aquí teniu dos tutorials nostres que us poden ajudar. Una introducció ràpida a la integració de React Hooks i Stripe Checkout amb React .

Unimedia Technology

A Unimedia Technology tenim un equip de desenvolupadors web que us poden ajudar a desenvolupar les vostres aplicacions React més complexes.

Recorda que a Unimedia som experts en tecnologies emergents, així que no dubtis a contactar amb nosaltres si necessites assessorament o serveis. Estarem encantats d’ajudar-te.

Unimedia Technology

El teu soci de desenvolupament de software

Som una consultoria tecnològica d’avantguarda especialitzada en arquitectura i desenvolupament de programari personalitzat.

Els nostres serveis

Registra't per rebre les nostres actualitzacions

Estigueu al dia, estigueu informat i donem forma junts al futur de la tecnologia!

Lectures relacionades

Aprofundeix amb aquests articles

Exploreu més coneixements experts d’Unimedia i anàlisis en profunditat en l’àmbit del desenvolupament de programari i la tecnologia.

Let’s make your vision a reality!

Simply fill out this form to begin your journey towards innovation and efficiency.

Fem realitat la teva visió!

Només has d’omplir aquest formulari per començar el teu viatge cap a la innovació i l’eficiència.