Introduction
Dans la première partie de cet article (dont voici), nous avons défini ce qu'est un projet MERN Stack et exploré les raisons pour lesquelles cette ensemble technologique suscite tant d'intérêt dans la communauté du développement web.
Dans cette deuxième partie nous nous concentrerons sur la création d'une application CRUD basique qui permet aux utilisateurs de créer, lire, modifier et supprimer les données dans la base de données en utilisant les technologies MERN.
Ces opérations CRUD seront implémentées côté serveur (avec Node.js et Express.js) pour exposer les endpoints REST API appropriés. Côté client (avec React.js), on pourra alors utiliser ces endpoints pour effectuer les interactions CRUD avec la base de données MongoDB.
C'est partie pour découvrir comment créer une application CRUD avec l'ensemble technologique MERN.
Construire un CRUD de base à l'aide de la pile MERN
Configuration de l'environnement
Avant de commencer, assurez-vous que les éléments suivants sont installés sur votre machine de développement.
- Node.js ( https://nodejs.org/ )
- npm (gestionnaire de packages de nœuds)
- MongoDB ( https://www.mongodb.com/try/download/community )
- Pour le style, j'ai utilisé Tailwind CSS ( https://tailwindcss.com/ ) qui est déjà disponible avec React
Etape1: configurer le projet
- Créez un nouveau répertoire de projet et initialisez un nouveau projet Node.js :
mkdir mern-crud-blog
cd mern-crud-blog
npm init -y
- Installez les dépendances requises :
npm install express mongoose body-parser cors
- Installez React du côté client :
npm install -D vite
cd client
npm install react-dom react-scripts axios
- Mettre en plae la sutrure du projet:
mern-crud-blog
├── client
│ └── public
│ | └── index.html
| | └── images and more.....
│ └── src
│ ├── components
│ ├── App.jsx
│ └── index.jsx
│ └── package.json
├── server.js
└── package.json
Etape2: Implémenter le backend (Node.js avec Express et MongoDB)
- Créez un fichier nommé
server.js
dans le répertoire racine et ajouter le code suivant :
// server.js
//1.Création du serveur.......................................
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const app = express();
const port = 5000;
// Activation de CORS pour autoriser les requêtes en provenance d'autres serveurs
app.use(cors());
// Code nécessaire pour analyser le body HTML dans la réponse
app.use(bodyParser.json());
// Etablir la connexion avec mongoDb
mongoose.connect('mongodb://localhost:27017/mern_crud_blog', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.on('error', console.error.bind(console, 'Erreur de connexion avec MongoDB:'));
db.once('open', () => {
console.log('Connexion à MongoDB réussie');
});
// nous ajouterons des routes ici à l'avenir .....
// Avance pour en savoir plus
// Création du schéma étudiants
const Schema = mongoose.Schema;
const StudentSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
}, { timestamps: true });
// Création du Schéma projets
const ProjectSchema = new Schema({
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
}, { timestamps: true });
const Student = mongoose.model('Student', StudentSchema);
const Project = mongoose.model('Project', ProjectSchema);
app.listen(port, () => {
console.log(`Le Serveur écoute sur le port ${port}`);
});
Etape3: Implémenter le frontend (React.js et Tailwind pour le style)
- Dans le dossier
client
, créez un nouveau fichier nomméindex.js
et ajoutez le code suivant :
Assurez vous d'avoir installer Tailwind dans votre projet
// client/src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// Si tu veux commencer à mesurer les performances de ton application, passe une fonction
// pour enregistrer les résultats (par exemple : reportWebVitals(console.log))
// ou envoie-les à un point d'analyse. Apprends-en plus : https://bit.ly/CRA-vitals
reportWebVitals();
- Créez un nouveau fichier nommé
App.jsx
dans le même répertoire et ajoutez le code suivant :
// client/src/App.jsx
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { BrowserRouter as Router, Route, Link, Routes } from 'react-router-dom';
import StudentList from './components/StudentList';
import ProjectList from './components/ProjectList';
import AddEditProject from './components/AddEditProject';
import AddEditStudent from './components/AddEditStudent';
import Home from './components/Home';
const App = () => {
// Hooks d'état et d'effet
const [Students, setStudents] = useState([]);
const [Projects, setProjects] = useState([]);
axios.defaults.baseURL = `http://localhost:5000`
useEffect(() => {
fetchStudents();
fetchProjects();
}, []);
//Récupération de tous les étudiants dans la base de données
const fetchStudents = async () => {
try {
const response = await axios.get('/api/Students');
setStudents(response.data.data);
console.log(response);
} catch (error) {
console.error('Error fetching Students:', error);
}
};
//Récupération de tous les projets dans la base de données
const fetchProjects = async () => {
try {
const response = await axios.get('/api/Projects');
setProjects(response.data.data);
} catch (error) {
console.error('Error fetching Projects:', error);
}
};
// Suppression d'un étudiant
const deleteStudent = async (id) => {
try {
await axios.delete(`/api/Students/${id}`);
fetchStudents(); // Fetch Students after deleting a Student
} catch (error) {
console.error('Error deleting Student:', error);
}
};
// Suppression d'un projet
const deleteProject = async (id) => {
try {
await axios.delete(`/api/Projects/${id}`);
fetchProjects(); // Fetch Projects after deleting a Project
} catch (error) {
console.error('Error deleting Project:', error);
}
};
return (
<div className="mx-auto app h-[100vh]">
<Router>
<div className='flex flex-row bg-black py-4 px-4 justify-between align-middle items-center'>
{/** Header */}
<div>
<h1 className="text-3xl font-bold text-white">Inscription PhD Géologie Numérique</h1>
<small className="text-1xl font-bold text-white">MERN Stack CRUD Application</small>
</div>
<div className="flex">
<div className="mr-4">
<Link to="/" className="hover:bg-blue-500 rounded-2xl text-white px-2 py-1 rounded">
Accuel
</Link>
</div>
<div className="mr-4">
<Link to="/Students" className="hover:bg-blue-500 rounded-2xl text-white px-2 py-1 rounded">
Etudiants
</Link>
</div>
<div className='mr-4'>
<Link to="/Projects" className="hover:bg-blue-500 rounded-2xl text-white px-2 py-1 rounded">
Projects
</Link>
</div>
</div>
</div>
<div className=" w-[100%] h-[100%] flex mx-auto w-1/2 place-self-center place-content-center self-center ">
<div className="flex flex-col bg-gray-600 pt-[2.5rem] w-[18rem]">
<Link to="/" className="text-xl font-bold text-white">
<div className={"pl-[2.5rem] hover:bg-blue-500 pt-[1rem] pb-[1rem] m-[5px] rounded-2xl"}>
Accuel
</div>
</Link>
<Link to="/Students" className="text-xl font-bold text-white">
<div className="pl-[2.5rem] hover:bg-blue-500 pt-[1rem] pb-[1rem] m-[5px] rounded-2xl">
Liste des étudiants
</div>
</Link>
<Link to="/Projects" className="text-xl font-bold text-white">
<div className='pl-[2.5rem] hover:bg-blue-500 pt-[1rem] pb-[1rem] m-[5px] rounded-2xl'>
Projet d'études
</div>
</Link>
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/Students" element={<StudentList Students={Students} fetchStudents={fetchStudents} deleteStudent={deleteStudent} />} />
<Route path="/Projects" element={<ProjectList Projects={Projects} fetchProjects={fetchProjects} deleteProject={deleteProject} />} />
<Route path="/add-Project" element={<AddEditProject fetchProjects={fetchProjects} />} />
<Route path="/add-Student" element={<AddEditStudent fetchStudents={fetchProjects} />} />
<Route path="/edit-Project/:id" element={<AddEditProject fetchProjects={fetchProjects} />} />
<Route path="/edit-Student/:id" element={<AddEditStudent fetchStudents={fetchProjects} />} />
</Routes>
</div>
</Router>
</div>
);
};
export default App;
Étape 4 : implémenter des routes backend pour les utilisateurs et les produits
- Dans le fichier
server.js
, ajoutez les routes suivantes pour les opérations CRUD des utilisateurs et des produits :
// server.js
// ... (code précédent)
//2. Routes pour les étudiants..............................
// Récupération de tous les utilisateurs
app.get('/api/Students', (req, res) => {
Student.find().then(item => {
console.log(item);
res.status(200).json({ message: 'Item fetched successfully', data: item, });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// récupérer un seul utilisateur
app.get('/api/Students/:id', (req, res) => {
const { id } = req.params;
Student.find({_id:id}).then(item => {
console.log(item);
res.status(200).json({ message: 'Item fetched successfully', data: item, });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// créer un nouvel étudiant
app.post('/api/Students', (req, res) => {
const newStudent = new Student(req.body);
console.log(newStudent);
newStudent.save().then(item => {
console.log(item);
res.status(201).json({ message: 'Item added successfully' });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Mettre à jour (modifier)le nouvel étudiant
app.put('/api/Students/:id', (req, res) => {
const { id } = req.params;
Student.findByIdAndUpdate(id, req.body, { new: true }).then(item => {
console.log(item);
res.status(203).json({ message: 'Item Fetched Successfully', data:item });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Supprimer un étudiant
app.delete('/api/Students/:id', (req, res) => {
const { id } = req.params;
Student.findByIdAndRemove(id).then(item => {
console.log(item);
res.status(203).json({ message: 'Item Fetched Successfully', data:item });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// 3. Routes pour les projets................................
// Récupération de tous les projets
app.get('/api/Projects', (req, res) => {
Project.find().then(item => {
console.log(item);
res.status(201).json({ message: 'Projects Fetched Successfully!', data: item });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Récupération d'un seul projet
app.get('/api/Projects/:id', (req, res) => {
const { id } = req.params;
Project.find({_id:id}).then(item => {
console.log(item);
res.status(200).json({ message: 'Item fetched successfully', data: item, });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Création d'un nouveau projet
app.post('/api/Projects', (req, res) => {
const newProject = new Project(req.body);
newProject.save().then(item => {
console.log(item);
res.status(201).json({ message: 'Item added successfully' });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Mettre à jour (modifier) un projet
app.put('/api/Projects/:id', (req, res) => {
const { id } = req.params;
Project.findByIdAndUpdate(id, req.body, { new: true }).then(item => {
console.log(item);
res.status(203).json({ message: 'Item Fetched Successfully', data:item });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// Supprimet un projet
app.delete('/api/Projects/:id', (req, res) => {
const { id } = req.params;
Project.findByIdAndRemove(id).then(item => {
res.status(203).json({ message: 'Deleted Successfully' });
})
.catch(err => {
console.log(err);
res.status(500).json({ message: 'Server error' });
});
});
// ... (code restant)
Étape 5 : implémenter des composants frontend pour les utilisateurs et les produits
- Dans le répertoire
client/src/components
, créez un fichier nommésHome.jsx
et ajoutez le code suivant :
// client/src/components/UserList.js
import React, { useEffect } from 'react';
const Home = () => {
return (
<div className='mt-10 flex flex-col mx-auto w-[70%]'>
<div>
<h1 className="text-[3rem] font-bold mb-2">Inscription PhD Géologie Numérique</h1>
<h2 className="text-xl font-bold mb-2">Aprennez l'approche numérique de la géologie de terrain</h2>
<p>Pour vous inscrire au programme de formation, vous devez fournir vos infromations proposer un projet de recherche.</p>
<br />
<div className=''>
<img className='w-[25rem]' src="https://www.researchgate.net/profile/Remi-Valois/publication/278637347/figure/fig33/AS:332216954572802@1456218102119/Modele-numerique-de-terrain-avec-une-coupe-geologique-du-secteur-central-du-Causse-de.png" alt="" />
</div>
<br />
<p>Pour plus d'information contactez cliquez <a className='text-blue-500' href='https://ger-cub.github.io/portfoliogerard/'>ici.</a></p>
<br />
<h1 className="text-[.6rem] font-[200] mb-2">MERN Stack CRUD Application Demostration ©Gerard-Mai/2024</h1>
</div>
</div>
);
};
export default Home;
- Dans le répertoire
client/src/components
, créez deux fichiers nommésStudentList.jsx
,ProjectList.jsx
et ajoutez le code suivant :
// client/src/components/StudentList.jsx
// client/src/components/StudentList.js
import React, { useEffect } from 'react';
import { Link, useSearchParams, useNavigate } from 'react-router-dom';
const StudentList = ({ Students, deleteStudent, fetchStudents }) => {
const navigate = useNavigate();
const editStudent = (id) => {
navigate(`/edit-Student/${id}`);
}
useEffect(() => {
fetchStudents()
}, [])
return (
<div className=' mt-10 flex flex-col mx-auto w-[70%] overflow-y-auto'>
<div className='justify-between flex'>
<h2 className="text-xl font-bold mb-2">Liste des étudiants</h2>
<Link to="/add-Student" className="bg-blue-500 text-white px-2 py-1 rounded">
Ajouter un étudiant
</Link>
</div>
<table className="table-auto mt-10 w-full">
<thead>
<tr>
<th className="px-4 border py-2">Noms</th>
<th className="px-4 border py-2">Adresses mails</th>
<th className="px-4 border py-2">Actions</th>
</tr>
</thead>
<tbody>
{Students?.length
?
Students.map((Student) => (
<tr key={Student._id}>
<td className="border px-4 py-2 text-center">{Student.name}</td>
<td className="border px-4 py-2 text-center">{Student.email}</td>
<td className="border px-4 py-2 flex flex-nowrap justify-center">
<button
className="bg-green-500 text-white px-2 py-1 rounded"
onClick={() => editStudent(Student._id)}
>
Modifier
</button>
<button
className="bg-red-500 ms-2 text-white px-2 py-1 rounded"
onClick={() => deleteStudent(Student._id)}
>
Supprimer
</button>
</td>
</tr>
))
:
<td className="border px-4 py-2 text-center" rowSpan={10} colSpan={10}>La liste est encore vide</td>
}
</tbody>
</table>
</div>
);
};
export default StudentList;
// client/src/components/ProjetList.jsx
// client/src/components/ProjectList.js
import React, { useEffect } from 'react';
import { Link, useNavigate } from 'react-router-dom';
const ProjectList = ({ Projects, deleteProject, fetchProjects }) => {
const navigate = useNavigate();
const editProject = (id) => {
navigate(`/edit-Project/${id}`);
}
useEffect(() => {
fetchProjects();
}, [])
return (
<div className='mt-10 flex flex-col mx-auto w-[70%] max-h-[80vh] overflow-y-auto'>
<div className='justify-between flex'>
<h2 className="text-xl font-bold mb-2">Liste des projets</h2>
<Link to="/add-Project" className="bg-blue-500 text-white px-2 py-1 rounded">
Ajouter un projet
</Link>
</div>
<table className="table-auto mt-10 w-full">
<thead>
<tr>
<th className="px-4 border py-2">Noms</th>
<th className="px-4 border py-2">Description</th>
<th className="px-4 border py-2">Coût</th>
<th className="px-4 border py-2">Actions</th>
</tr>
</thead>
<tbody>
{
Projects?.length ?
Projects.map((Project) => (
<tr key={Project._id}>
<td className="border px-4 py-2 text-center">{Project.name}</td>
<td className="border px-4 py-2 text-center">{Project.description}</td>
<td className="border px-4 py-2 text-center">${Project.price}</td>
<td className="border px-4 py-2 flex flex-nowrap justify-center">
<button
className="bg-green-500 text-white px-2 py-1 rounded"
onClick={() => editProject(Project._id)}
>
Modifier
</button>
<button
className="bg-red-500 text-white px-2 ms-2 py-1 rounded"
onClick={() => deleteProject(Project._id)}
>
Supprimer
</button>
</td>
</tr>
)) :
<td className="border px-4 py-2 text-center" rowSpan={10} colSpan={10}>La liste est encore vide</td>
}
</tbody>
</table>
</div>
);
};
export default ProjectList;
- Dans le client/src/componentsrépertoire, créez deux fichiers nommés
AddEditStudent.jsx
etAddEditProject.jsx
, et ajoutez le code suivant :
// client/src/pages/AddEditProject.js
// client/src/pages/AddEditProject.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate, useParams } from 'react-router-dom';
const AddEditProject = ({ fetchProjects = null }) => {
const navigate = useNavigate();
const { id } = useParams();
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [price, setPrice] = useState('');
useEffect(() => {
if (id) {
fetchProject();
}
}, [id]);
const fetchProject = async () => {
try {
const response = await axios.get(`/api/Projects/${id}`);
setName(response.data.data[0].name);
setDescription(response.data.data[0].description);
setPrice(response.data.data[0].price);
} catch (error) {
console.error('Error fetching Project:', error);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const newProject = { name, description, price: Number(price) };
if (id) {
try {
await axios.put(`/api/Projects/${id}`, newProject);
navigate('/Projects');
} catch (error) {
console.error('Error updating Project:', error);
}
} else {
try {
await axios.post('/api/Projects', newProject);
fetchProjects(); // Fetch Projects after adding a new Project
navigate('/Projects');
} catch (error) {
console.error('Error adding Project:', error);
}
}
};
// Compteur des mots
const compterMots = () => {
const mots = description.split(' ');
return mots.length - 1;
};
return (
<div className='w-[85%] p-[5rem]'>
<h2 className="text-xl font-bold mb-2">{id ? 'Ajoutez votre' : 'Modifiez votre'} Projet</h2>
<form onSubmit={compterMots() <= 450 && handleSubmit}>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="name">
Nom complet
</label>
<input
type="text"
id="name"
name="name"
value={name}
placeholder='Nom Postnom Prenom'
onChange={(e) => setName(e.target.value)}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="description">
Bref description de votre Projet de recherche / Sujet, Problèmatique, Objectifs, Méthodologies et resultat attendus / 450 mots max
</label>
<textarea
id="description"
name="description"
value={description}
onChange={(e) => setDescription(e.target.value)}
required
className="shadow appearance-none border h-[15rem] rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
<small className={compterMots() < 450 ? 'text-green-500 text-justify' : 'text-red-500 text-justify'}>{compterMots()} mots.</small>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="price">
Coût estimé en $
</label>
<input
type="number"
id="price"
name="price"
value={price}
onChange={(e) => setPrice(e.target.value)}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
<div>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
>
Enregister
</button>
</div>
</form>
</div>
);
};
export default AddEditProject;
A ce stade votre application devrait ressemblé à ceci :
// client/src/pages/AddEditStudent.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import { useNavigate,useSearchParams, useParams } from 'react-router-dom';
const AddEditStudent = ({ fetchStudents }) => {
const navigate = useNavigate();
const { id } = useParams();
const [name, setname] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
useEffect(() => {
if (id) {
console.log('here');
fetchStudent();
}
}, [id]);
const fetchStudent = async () => {
try {
const response = await axios.get(`/api/Students/${id}`);
setname(response.data.data[0].name);
setEmail(response.data.data[0].email);
setPassword(response.data.data[0].password);
} catch (error) {
console.error('Error fetching Student:', error);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const newStudent = { name, email, password };
if (id) {
try {
await axios.put(`/api/Students/${id}`, newStudent);
navigate('/Students');
} catch (error) {
console.error('Error updating Student:', error);
}
} else {
try {
await axios.post('/api/Students', newStudent);
fetchStudents(); // Fetch Students after adding a new Student
navigate('/Students');
} catch (error) {
console.error('Error adding Student:', error);
}
}
};
return (
<div className='w-[85%] p-[5rem]'>
<h2 className="text-xl font-bold mb-2"> {id ? 'Modifier' : 'Ajouter'} l'étudiant</h2>
<form onSubmit={handleSubmit} className='w-[70%]'>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="name">
Nom
</label>
<input
type="text"
id="name"
name="name"
value={name}
onChange={(e) => setname(e.target.value)}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
Adresse mail
</label>
<input
type="email"
id="email"
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
Mot de passe
</label>
<input
type="password"
id="password"
name="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>
</div>
<div>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
>
Enregistrer
</button>
</div>
</form>
</div>
);
};
export default AddEditStudent;
Dans le fichier client/src/App.jsx
, vous avez déjà importé les composants StudentList
et ProjectList
pour les afficher dans le Appcomposant, extrayez à nouveau le code.
Étape 6 : tester l'application
Si vous êtes sous Windows ou Mac, vous pouvez utiliser l'interface graphique pour démarrer le serveur MongoDb, sinon sous Linux, vous pouvez utiliser mongod
la commande pour exécuter le service.
- Ouvrez un nouveau terminal et démarrez le serveur MongoDB :
mongod
- Dans un autre terminal, démarrez le serveur Node.js :
serveur de nœud.js
- Dans un troisième terminal, accédez au client répertoire et démarrez le serveur de développement React :
client cd
démarrage npm
- Ouvrez votre navigateur Web et accédez
http://localhost:3000
à l'application d'Inscription MERN Stack CRUD Application.
Pour la référence GitHub
https://github.com/Ger-Cub/inscription-phd-mern-crud-app
Deploy a MERN STACK app on Render platform in 2024
(https://www.youtube.com/watch?v=ZsFwpjFmpFQ)
Choses à ne jamais oublier :
Adoptez la documentation comme boussole pour plus de clarté et de progrès.
Nourrissez un esprit curieux en vous demandant : « Qu’ai-je fait et pourquoi l’ai-je fait ? » à chaque étape.
Pratiquez la pleine conscience et restez concentré pour exceller dans n’importe quelle entreprise.
L'amélioration continue est un voyage, et même avec un dépôt GitHub minutieusement testé et à jour, soyez ouvert à tout commentaire pour améliorer davantage le code.
Merci d'avoir lu jusqu'au bout. Veuillez envisager de suivre l’écrivain et cette publication. Visitez Stackademic pour en savoir plus sur la façon dont nous démocratisons l’enseignement gratuit de la programmation dans le monde.
Top comments (0)