Académique Documents
Professionnel Documents
Culture Documents
Préparation projet
Créer un dossier projet et entrez dedans
mkdir tuto_crud_mongo
cd tuto_crud_mongo
npx create-next-app@latest .
Installing devDependencies:
- autoprefixer
- postcss
- tailwindcss
- eslint
- eslint-config-next
Installez ensuite mongoose , un ORM pour interagir avec mongodb. et react-icons pour des
icones.
O l d i d V C d
On ouvre le dossier dans Vs-Code
Dans le terminal on tapes :
Dans le navigateur on a :
Ne laissez que :
@tailwind base;
@tailwind components;
@tailwind utilities;
Modification de la page.js
Dans app , renommez page.js en page.jsx
<h2>Coucou</h2>
);
}
Composant Navbar.jsx
import Link from "next/link"
Composant RemoveBtn.jsx
import { HiOutlineTrash } from "react-icons/hi"
Composant TopicsList.jsx
import RemoveBtn from "@/components/RemoveBtn";
import Link from "next/link";
import { HiPencilAlt } from "react-icons/hi";
Modification du layout
Toutes les pages vont partager le layout.jsx , on y placera donc le composant navbar
Dans editTopic/[id]/page.jsx
Testez
On a :
Création du composant EditTopicForm
Dans components\EditTopicForm/page.jsx
Copiez le formulaire à partir de app\addTopic\page.jsx
Dans app\editTopic\page.tsx
BACK END
Installation MongoDB (en version cloud)
MongoDB peut être installé sur votre machine local ou être utilisé en version cloud database.
Nous allons créer une base de donnée MongoDB à partir de leur cloud. (https://www.mongodb.co
m/atlas)
Pour avoir accès au cloud MongoDB et ensuite pouvoir créer votre propre base de données,
rendez-vous au https://www.mongodb.com/atlas et cliqué sur le bouton "Try Free".
Cliquez sur "Build a Database", ensuite choisir l'option "Free Shared" et cliquer sur "Create".
Ensuite, conserver les options par défaut sauf la dernière option qui est "Cluster Name" et
changer le nom pour "NodeExpress". Enfin cliquer sur "Create Cluster"
Mot de passe
Username : trentin
NqGpQKTbtcMdWtsy
Ensuite tapez dans IP Adresss la valeur 0.0.0.0/0 ce qui permet de se connecter à votre
base de données de n'importe où (pour le tuto).
Les fichiers .env permettent de stocker des configurations spécifiques au projet, telles que
des identifiants de base de données, des clés API, et d'autres secrets, de manière sécurisée
et centralisée.
MONGODB_URI=mongodb+srv://trentin:<password>@cluster0.r5dczs2.mongodb.net/crud_db
Remplacer <password> par le mot de passe que vous avez noté précédemment.
vous pouvez ajouter .env dans votre .gitignore pour éviter d'exposer vos variables
d'environnement.
} catch (error) {
console.log(error)
}
}
Modéles
// topic.js
import mongoose, { Schema } from "mongoose";
Ce code utilise Mongoose, une bibliothèque ODM (Object Data Modeling) pour MongoDB et
Node.js, pour définir un modèle de données pour une collection MongoDB appelée "Topic"
2. Définition du Schéma : topicSchema est défini comme une nouvelle instance de Schema .
Ce schéma décrit la structure des documents dans la collection "Topic" avec deux champs :
title et description , tous deux de type String . L'option timestamps: true ajoute
automatiquement deux champs : createdAt et updatedAt , qui enregistrent la date de
création et la dernière modification du document[4].
Création de l'API
Pour créer les routes des api, on va utiliser le mode de programmation asynchrone avec
async et await pour gérer les opérations de base de données de manière efficace et non
bloquante.
} catch (error) {
console.log(error)
}
}
Explications
1. Importations :
2. Fonction POST :
Cette fonction asynchrone prend une requête HTTP request , extrait les données JSON
( title , description ), se connecte à MongoDB, crée un nouveau document Topic
avec ces données, et retourne une réponse JSON indiquant que l'article a été créé, avec
un code de statut HTTP 201 (Créé).
{
"title":"CSS",
"description": "A cascading style sheet for websites"
}
Et
{
"title":"React",
"description": "A front End Framework for modern websites"
}
-Dans Atlas, rafraichissez la page.
// app>api>topics> route.js
Explications
Renvoi des données : La dernière ligne, return NextResponse.json({ topics }); , utilise
NextResponse (une API de Next.js pour manipuler les réponses HTTP) pour envoyer les données
récupérées ( topics ) au client au format JSON. Cela permet au frontend de l'application d'accéder
et d'afficher ces données[1].
Explications
La fonction PUT :
PUT
(qui correspond à la méthode HTTP PUT utilisée pour la mise à jour de ressources sur le
serveur) et on l'exporte pour qu'elle puisse être utilisée ailleurs dans l'application. Elle prend
deux paramètres :
request : L'objet de la requête HTTP entrante, contenant les données envoyées par le
client.
{ params } : Un objet déstructuré (*) directement extrait de l'argument de contexte,
contenant les paramètres de route, comme l' id de l'article à mettre à jour.
const { id } = params; : On extrait l' id de l'article à mettre à jour depuis les paramètres
de la requête.
(*) La déstructuration d'objet dans JavaScript est une syntaxe expressive et concise pour
extraire des valeurs de propriétés d'un objet. Dans la ligne de code const { id } =
params; , la déstructuration est utilisée pour extraire la valeur de la propriété id de l'objet
params .
params est un objet qui contient des paires clé-valeur. Par exemple, il pourrait
ressembler à { id: '123', autrePropriete: 'valeur' } .
Cette syntaxe rend le code plus lisible et moins verbeux, car elle évite d'avoir à accéder à la
propriété de l'objet de manière explicite (par exemple, const id = params.id; ). Elle est
particulièrement utile pour extraire plusieurs propriétés d'un objet en une seule instruction.
//....
if (!res.ok) {
throw new Error("Fetch a échoué");
}
return res.json();
} catch (error) {
console.log("Erreur de chargement d'article: ", error);
}
};
SI vous avez des messages d'erreurs concernant la présence obligatoire de key dans le map ,
vous pouvez ajouter :
/* eslint-disable react/jsx-key */
Explications
Le deuxième argument passé à la fonction fetch() est un objet de configuration. Dans cet
exemple, il y a une seule propriété définie dans cet objet :
/* eslint-disable react/jsx-key */
import RemoveBtn from "@/components/RemoveBtn";
import Link from "next/link";
import { HiPencilAlt } from "react-icons/hi";
if (!res.ok) {
throw new Error("Fetch a échoué");
}
return res.json();
} catch (error) {
console.log("Erreur de chargement d'article: ", error);
}
};
Il est très courant d'utiliser une fonction anonyme avec la méthode map() pour générer un
fragment de code ou un composant pour chaque élément d'un tableau et les afficher en
utilisant React ou une autre bibliothèque front-end.
Vérification
Modification de AddTopic/page.jsx
Par default dans Next.js les composants sont des composants serveur
Next.js supporte plusieurs formes de rendu : côté serveur (SSR), statique (SSG), et côté client.
Voici pourquoi 'use client' peut être utilisé :
1. Rendu Client-Side : L'indication 'use client' dans un composant React spécifie que ce
composant doit être rendu exclusivement côté client. Cela signifie que le composant ne
sera pas pré-rendu sur le serveur lors de la génération de la page, mais sera plutôt
exécuté et rendu dans le navigateur de l'utilisateur. Cela peut être utile pour des
parties de l'application qui dépendent fortement des interactions utilisateur
(comme les formulaires) ou des données spécifiques au client qui ne sont pas
disponibles lors du rendu côté serveur.
3. Séparation des préoccupations : Utiliser 'use client' aide à séparer clairement les
composants qui doivent être rendus côté serveur de ceux exclusivement destinés au
rendu côté client. Cela simplifie le développement et la maintenance en permettant aux
développeurs de concentrer leurs efforts d'optimisation sur les parties spécifiques de
l'application qui bénéficient le plus du rendu côté client.
"use client";
if (!title || !description) {
alert("Le title et la description sont requis.");
return;
}
try {
const res = await fetch("http://localhost:3000/api/topics", {
method: "POST",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ title, description }),
});
if (res.ok) {
router.push("/");
} else {
throw new Error("La créatoin d'article a échoué");
}
} catch (error) {
console.log(error);
}
};
return (
<form onSubmit={handleSubmit} className="flex flex-col gap-3">
<input
onChange={(e) => setTitle(e.target.value)}
value={title}
className="border border-slate-500 px-8 py-2"
type="text"
placeholder="Titre Article"
/>
<input
onChange={(e) => setDescription(e.target.value)}
value={description}
className="border border-slate-500 px-8 py-2"
type="text"
placeholder="Description de l'Article"
/>
<button
type="submit"
className="bg-green-600 font-bold text-white py-3 px-6 w-fit"
>
Ajouter
</button>
</form>
);
}
Explications
La directive "use client" indique que ce code est destiné à s'exécuter sur le navigateur client et
non sur le serveur.
Deux états sont déclarés à l'aide du Hook useState : title pour stocker le titre et
description pour stocker la description. Les fonctions setTitle et setDescription
permettent de mettre à jour ces états respectifs.
La fonction handleSubmit est définie. Elle est appelée lors de la soumission du formulaire et
est définie comme une fonction asynchrone.
Ensuite, on vérifie si title et description sont vides. Si c'est le cas, une alerte est affichée
demandant de remplir les champs requis.