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ó.
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>
)
}
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.
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.
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 />} />
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 />}/>
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.