💡 React et Laravel – CrĂ©ation CRUD

💡 React et Laravel – CrĂ©ation CRUD

Réaliser un CRUD (« Create, Read, Update, Delete ») dans une application React en utilisant Axios.

📌 Installation de l’API

  • Installez ou rĂ©activez l’API Laravel « Tuto-Laravel-API » via le lien GitHub indiquĂ© plus haut.
  • CrĂ©ez une nouvelle base de donnĂ©es.
  • Configurez le fichier .env pour connecter votre base de donnĂ©es Ă  votre API.
  • ExĂ©cutez composer update pour installer les dĂ©pendances.
  • ExĂ©cutez php artisan migrate pour crĂ©er les tables.

📌 Installation de l’application React.js

npx create-react-app nom-de-votre-projet
cd nom-de-votre-projet

 

Installez les dépendances :

npm i -s react-router-dom sass react-bootstrap bootstrap axios

Importez Bootstrap dans index.js :

import 'bootstrap/dist/css/bootstrap.min.css';

Lancez votre projet :

npm start

📌 CrĂ©ation du systĂšme de routage

Créez le dossier pages dans src avec les fichiers suivants :

- src/pages/clubs/Clubs.jsx
- src/pages/clubs/AddClub.jsx
- src/pages/clubs/EditClub.jsx
- src/pages/players/Players.jsx
- src/pages/players/AddPlayer.jsx
- src/pages/players/EditPlayer.jsx
- src/pages/Home.jsx

 

Une fois ces fichiers crées, paramétrez vos routes dans le fichier app.js :

// Importation des bibliothĂšques React et React Router
import React from 'react';
import { BrowserRouter, Routes, Route } from "react-router-dom";

// Importation des composants/pages pour la navigation
import Clubs from './pages/clubs/Clubs';
import AddClub from './pages/clubs/AddClub';
import EditClub from './pages/clubs/EditClub';
import Players from './pages/players/Players';
import AddPlayer from './pages/players/AddPlayer';
import EditPlayer from './pages/players/EditPlayer';
import Home from "./pages/Home";

// Définition du composant principal App
function App() {
    return (
        // BrowserRouter est le conteneur principal qui permet la gestion du routage
        <BrowserRouter>
            {/* Routes englobe toutes les routes définies pour l'application */}
            <Routes>

                {/* Route principale : affichage de la page d'accueil */}
                <Route path="/" element={<Home />} />

                {/* Routes pour la gestion des clubs */}
                <Route path="/clubs" element={<Clubs />} />  {/* Liste des clubs */}
                <Route path="/clubs/add" element={<AddClub />} />  {/* Ajout d'un club */}
                <Route path="/clubs/edit/:club" element={<EditClub />} />  {/* Modification d'un club */}

                {/* Routes pour la gestion des joueurs */}
                <Route path="/players" element={<Players />} />  {/* Liste des joueurs */}
                <Route path="/players/add" element={<AddPlayer />} />  {/* Ajout d'un joueur */}
                <Route path="/players/edit/:player" element={<EditPlayer />} />  {/* Modification d'un joueur */}

                {/* Route par défaut : redirige vers Home si aucune route ne correspond */}
                <Route path="*" element={<Home />} />

            </Routes>
        </BrowserRouter>
    );
}

// Exportation du composant App pour qu'il puisse ĂȘtre utilisĂ© ailleurs dans l'application
export default App;

 

📌 CrĂ©ation des composants

Le menu

Créez un fichier Menu.jsx dans src/components/ et intégrez-le dans Home.jsx.

// Importation des bibliothĂšques React et des composants Bootstrap pour la barre de navigation
import React from "react";
import Container from "react-bootstrap/Container";
import Nav from "react-bootstrap/Nav";
import Navbar from "react-bootstrap/Navbar";
import NavDropdown from "react-bootstrap/NavDropdown";

// Définition du composant Menu
const Menu = () => {
    return (
        <div>
            {/* Création de la barre de navigation Bootstrap */}
            <Navbar bg="light" expand="lg">
                <Container fluid>

                    {/* Bouton pour afficher/cacher le menu en mode responsive */}
                    <Navbar.Toggle aria-controls="navbarScroll" />

                    {/* Contenu du menu déroulant */}
                    <Navbar.Collapse id="navbarScroll">
                        <Nav
                            className="me-auto my-2 my-lg-0"
                            style={{ maxHeight: "100px" }}
                            navbarScroll
                        >

                            {/* Lien vers la page d'accueil */}
                            <Nav.Link href="/">Home</Nav.Link>

                            {/* Menu déroulant pour la gestion des clubs */}
                            <NavDropdown title="Clubs" id="navbarScrollingDropdown">
                                <NavDropdown.Item href="/clubs/add">
                                    Créer un nouveau club
                                </NavDropdown.Item>
                                <NavDropdown.Item href="/clubs">
                                    Liste des clubs
                                </NavDropdown.Item>
                            </NavDropdown>

                            {/* Menu déroulant pour la gestion des joueurs */}
                            <NavDropdown title="Joueurs" id="navbarScrollingDropdown">
                                <NavDropdown.Item href="/players/add">
                                    Créer un nouveau joueur
                                </NavDropdown.Item>
                                <NavDropdown.Item href="/players">
                                    Liste des joueurs
                                </NavDropdown.Item>
                            </NavDropdown>

                        </Nav>
                    </Navbar.Collapse>

                </Container>
            </Navbar>
        </div>
    );
};

// Exportation du composant Menu pour ĂȘtre utilisĂ© dans d'autres fichiers
export default Menu;

Une fois le composant Menu.jsx codé, intégrez-le à la page Home pour le tester :

// Importation de React et du composant Component pour la création d'un composant de classe
import React, { Component } from 'react';

// Importation du composant Menu qui sera affiché sur la page d'accueil
import Menu from '../components/Menu';

// Définition du composant Home en tant que classe React
export class Home extends Component {
    // La méthode render() permet d'afficher le contenu du composant
    render() {
        return (
            <div>
                {/* Affichage du menu de navigation */}
                <Menu />
            </div>
        );
    }
}

// Exportation du composant Home pour ĂȘtre utilisĂ© dans d'autres fichiers
export default Home;

 

📌 Mise en place des formulaires

Ajoutez les fichiers AddClub.jsx et AddPlayer.jsx avec les champs nécessaires pour la création.

// Importation des bibliothÚques React et des composants nécessaires de Bootstrap
import React, { useState } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import axios from "axios"; // BibliothĂšque pour effectuer les requĂȘtes HTTP
import { useNavigate } from "react-router-dom"; // Hook pour la navigation
import Menu from "../../components/Menu"; // Importation du menu de navigation

// Définition du composant AddClub
const AddClub = () => {
    // Hook pour la navigation aprĂšs la soumission du formulaire
    const navigate = useNavigate();

    // États pour stocker les valeurs des champs du formulaire
    const [nameClub, setNameClub] = useState(""); // Nom du club
    const [logoClub, setLogoClub] = useState(""); // Logo du club (fichier)
    const [validationError, setValidationError] = useState({}); // Stocke les erreurs de validation

    // Gestionnaire de changement pour le fichier du logo
    const changeHandler = (event) => {
        setLogoClub(event.target.files[0]); // Stocke le fichier sélectionné
    };

    // Fonction d'ajout d'un club via une requĂȘte HTTP POST
    const addClub = async (e) => {
        e.preventDefault(); // EmpĂȘche le rechargement de la page lors de la soumission du formulaire
        
        // CrĂ©ation d'un objet FormData pour envoyer des fichiers avec la requĂȘte
        const formData = new FormData();
        formData.append("nameClub", nameClub);
        formData.append("logoClub", logoClub);

        // Envoi de la requĂȘte Ă  l'API pour ajouter un club
        await axios
            .post(`http://127.0.0.1:8000/api/clubs`, formData)
            .then(() => navigate('/clubs')) // Redirige vers la liste des clubs aprĂšs succĂšs
            .catch(({ response }) => {
                if (response.status === 422) { // Si l'API retourne une erreur de validation
                    setValidationError(response.data.errors); // Stocke les erreurs
                }
            });
    };

    return (
        <div>
            {/* Affichage du menu de navigation */}
            <Menu />

            <div className="container">
                <div className="row justify-content-center">
                    <div className="col-12 col-sm-12 col-md-6">
                        <div className="card">
                            <div className="card-body">
                                <h4 className="card-title">Création d'un nouveau club</h4>
                                <hr />

                                <div className="form-wrapper">
                                    {/* Affichage des erreurs de validation si elles existent */}
                                    {Object.keys(validationError).length > 0 && (
                                        <div className="row">
                                            <div className="col-12">
                                                <div className="alert alert-danger">
                                                    <ul className="mb-0">
                                                        {Object.entries(validationError).map(([key, value]) => (
                                                            <li key={key}>{value}</li>
                                                        ))}
                                                    </ul>
                                                </div>
                                            </div>
                                        </div>
                                    )}

                                    {/* Formulaire d'ajout de club */}
                                    <Form onSubmit={addClub}>
                                        <Row>
                                            <Col>
                                                <Form.Group controlId="Name">
                                                    <Form.Label>Nom du club</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={nameClub}
                                                        onChange={(event) => setNameClub(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="Logo" className="mb-3">
                                                    <Form.Label>Logo</Form.Label>
                                                    <Form.Control type="file" onChange={changeHandler} />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        {/* Bouton de soumission du formulaire */}
                                        <Button
                                            variant="primary"
                                            className="mt-2"
                                            size="lg"
                                            block="block"
                                            type="submit"
                                        >
                                            Créer
                                        </Button>
                                    </Form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

// Exportation du composant AddClub pour ĂȘtre utilisĂ© ailleurs dans l'application
export default AddClub;

Puis rĂ©alisons le fichier d’ajout de joueur qui sera un peu plus compliquĂ© que celui des clubs car le formulaire d’ajout comporte une clĂ© Ă©trangĂšre Ă  renseigner (club_id). Ce code sera Ă  insĂ©rer dans le fichier AddPlayer.js :

// Importation des bibliothĂšques React et des composants Bootstrap pour le formulaire
import React, { useState, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import axios from "axios"; // Importation d'Axios pour les requĂȘtes HTTP
import { useNavigate } from "react-router-dom"; // Hook pour la navigation entre pages
import Menu from "../../components/Menu"; // Importation du menu de navigation

// Définition du composant AddPlayer pour l'ajout d'un joueur
const AddPlayer = () => {
    const navigate = useNavigate(); // Hook pour rediriger aprĂšs l'ajout

    // États pour stocker les valeurs du formulaire
    const [firstName, setFirstName] = useState(""); // Prénom du joueur
    const [lastName, setLastName] = useState(""); // Nom du joueur
    const [height, setHeight] = useState(""); // Taille du joueur
    const [position, setPosition] = useState(""); // Position sur le terrain
    const [club_id, setClubId] = useState(""); // ID du club sélectionné
    const [photoPlayer, setPhotoPlayer] = useState(""); // Fichier photo du joueur
    const [validationError, setValidationError] = useState({}); // Gestion des erreurs
    const [clubs, setClubs] = useState([]); // Liste des clubs disponibles

    // Gestionnaire de changement pour l'image (photo du joueur)
    const changeHandler = (event) => {
        setPhotoPlayer(event.target.files[0]); // Stocke le fichier sélectionné
    };

    // Gestionnaire de changement pour la sélection du club
    const handleChange = (event) => {
        setClubId(event.target.value); // Met à jour l'ID du club sélectionné
    };

    // useEffect pour charger la liste des clubs disponibles dÚs que le composant est monté
    useEffect(() => {
        getClubs();
    }, []);

    // Fonction pour rĂ©cupĂ©rer la liste des clubs via une requĂȘte GET
    const getClubs = async () => {
        await axios.get('http://127.0.0.1:8000/api/clubs')
            .then(res => {
                setClubs(res.data); // Stocke la liste des clubs dans le state
            });
    };

    // Fonction pour ajouter un joueur via une requĂȘte HTTP POST
    const addPlayer = async (e) => { 
        e.preventDefault(); // EmpĂȘche le rechargement de la page lors de la soumission

        // Création d'un objet FormData pour envoyer les données avec le fichier
        const formData = new FormData();
        formData.append("firstName", firstName);
        formData.append("lastName", lastName);
        formData.append("height", height);
        formData.append("position", position);
        formData.append("club_id", club_id);
        formData.append("photoPlayer", photoPlayer);

        console.log(club_id); // Affichage de l'ID du club sélectionné pour debug

        // Envoi des données au serveur
        await axios.post(`http://127.0.0.1:8000/api/players`, formData)
            .then(() => navigate("/players")) // Redirection vers la liste des joueurs aprĂšs succĂšs
            .catch(({ response }) => {
                if (response.status !== 200) {
                    setValidationError(response.data); // Stocke les erreurs de validation
                }
            });
    };

    return (
        <div>
            {/* Affichage du menu de navigation */}
            <Menu />

            <div className="container container mt-5">
                <div className="row justify-content-center">
                    <div className="col-12 col-sm-12 col-md-6">
                        <div className="card">
                            <div className="card-body">
                                <h4 className="card-title">Création d'un nouveau joueur</h4>
                                <hr />

                                <div className="form-wrapper">
                                    {/* Affichage des erreurs de validation */}
                                    {Object.keys(validationError).length > 0 && (
                                        <div className="row">
                                            <div className="col-12">
                                                <div className="alert alert-danger">
                                                    <ul className="mb-0">
                                                        {Object.entries(validationError).map(
                                                            ([key, value]) => (
                                                                <li key={key}>{value}</li>
                                                            )
                                                        )}
                                                    </ul>
                                                </div>
                                            </div>
                                        </div>
                                    )}

                                    {/* Formulaire d'ajout de joueur */}
                                    <Form onSubmit={addPlayer}>
                                        <Row>
                                            <Col>
                                                <Form.Group controlId="firstName">
                                                    <Form.Label>Prénom</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={firstName}
                                                        onChange={(event) => setFirstName(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="lastName">
                                                    <Form.Label>Nom</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={lastName}
                                                        onChange={(event) => setLastName(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="height">
                                                    <Form.Label>Taille</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={height}
                                                        onChange={(event) => setHeight(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="position">
                                                    <Form.Label>Position</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={position}
                                                        onChange={(event) => setPosition(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="club">
                                                    <Form.Label>Club</Form.Label>
                                                    <Form.Select aria-label="Sélection du club" onChange={handleChange}>
                                                        <option>Choisissez un club</option>
                                                        {clubs.map(club => (
                                                            <option key={club.id} value={club.id}>
                                                                {club.nameClub}
                                                            </option>
                                                        ))}
                                                    </Form.Select>
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="PhotoPlayer" className="mb-3">
                                                    <Form.Label>Photo du joueur</Form.Label>
                                                    <Form.Control type="file" onChange={changeHandler} />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        {/* Bouton de soumission */}
                                        <Button
                                            variant="primary"
                                            className="mt-2"
                                            size="lg"
                                            block="block"
                                            type="submit"
                                        >
                                            Créer un nouveau joueur
                                        </Button>
                                    </Form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

// Exportation du composant AddPlayer pour ĂȘtre utilisĂ© ailleurs
export default AddPlayer;

 

 

 

📌 CrĂ©ation des listes

Créez Clubs.jsx et Players.jsx pour afficher les données sous forme de tableau.

Dans le fichier Clubs.js :

// Importation des bibliothÚques React et des composants Bootstrap pour l'affichage des données
import React, { useEffect, useState } from "react";
import Table from "react-bootstrap/Table";
import Button from "react-bootstrap/Button";
import Menu from "../../components/Menu"; // Importation du menu de navigation
import axios from "axios"; // Importation d'Axios pour les requĂȘtes HTTP

// Définition du composant Clubs pour afficher la liste des clubs
const Clubs = () => {
    // Définition d'un état pour stocker les clubs récupérés depuis l'API
    const [clubs, setClubs] = useState([]);

    // useEffect est exécuté au montage du composant pour récupérer les clubs
    useEffect(() => {
        displayClubs();
    }, []); // Le tableau vide signifie que l'effet ne s'exécute qu'une seule fois

    // Fonction pour rĂ©cupĂ©rer la liste des clubs via une requĂȘte GET
    const displayClubs = async () => {
        await axios.get("http://127.0.0.1:8000/api/clubs").then((res) => {
            setClubs(res.data); // Stocke les clubs récupérés dans l'état
        });
    };

    // Fonction pour supprimer un club via une requĂȘte DELETE
    const deleteClub = (id) => {
        axios.delete(`http://127.0.0.1:8000/api/clubs/${id}`).then(displayClubs);
    };

    return (
        <div>
            {/* Affichage du menu de navigation */}
            <Menu />

            <div className="container mt-5">
                {/* Affichage du tableau des clubs */}
                <Table striped bordered hover>
                    <thead>
                        <tr>
                            <th>Nom du club</th>
                            <th>Logo</th>
                            <th>Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        {/* Boucle sur le tableau des clubs et affichage des données */}
                        {clubs.map((club) => (
                            <tr key={club.id}>
                                <td>{club.nameClub}</td>
                                <td>
                                    <img
                                        src={`http://127.0.0.1:8000/storage/uploads/${club.logoClub}`}
                                        width="75px"
                                        alt="Logo du club"
                                    />
                                </td>
                                <td>
                                    {/* Bouton pour supprimer un club */}
                                    <Button
                                        variant="danger"
                                        onClick={() => {
                                            deleteClub(club.id);
                                        }}
                                    >
                                        Supprimer
                                    </Button>
                                </td>
                            </tr>
                        ))}
                    </tbody>
                </Table>
            </div>
        </div>
    );
};

// Exportation du composant Clubs pour ĂȘtre utilisĂ© ailleurs
export default Clubs;

Si aprùs avoir copier le code vos images ne s’affichent pas entrez cette ligne de commande dans votre API :

#php artisan storage:link

 

📌 CrĂ©ation de l’update

L’update se construit de la mĂȘme maniĂšre que le create sauf que nous devons rĂ©cupĂ©rer les informations avant de les modifier.

Tout d’abord, on commence par ajouter le lien de modification dans le fichier Clubs.js au niveau de la colonne

« Actions » de votre tableau :

<Link to={`/clubs/edit/${club.id}`} className='btn btn-success me-2'>
Edit
</Link>

Pensez Ă  importer le composant Link en haut de votre fichier :

import { Link } from 'react-router-dom';

Ensuite compléter votre fichier EditClub.js de cette maniÚre :

// Importation des bibliothĂšques React et des composants Bootstrap pour le formulaire
import React, { useState, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Button from "react-bootstrap/Button";
import Row from "react-bootstrap/Row";
import Col from "react-bootstrap/Col";
import axios from "axios"; // BibliothĂšque pour effectuer les requĂȘtes HTTP
import { useNavigate, useParams } from "react-router-dom"; // Hooks pour la navigation et la récupération des paramÚtres d'URL
import Menu from "../../components/Menu"; // Importation du menu de navigation

// Définition du composant EditClub pour modifier un club existant
const EditClub = () => {
    // Récupération de l'ID du club depuis les paramÚtres de l'URL
    const { club } = useParams();

    // Hook pour rediriger aprĂšs la modification
    const navigate = useNavigate();

    // États pour stocker les valeurs des champs du formulaire
    const [nameClub, setNameClub] = useState(""); // Nom du club
    const [logoClub, setLogoClub] = useState(null); // Logo du club (fichier)
    const [validationError, setValidationError] = useState({}); // Gestion des erreurs de validation

    // useEffect pour récupérer les informations du club dÚs le chargement du composant
    useEffect(() => {
        getClub();
    }, []);

    // Fonction pour rĂ©cupĂ©rer les informations du club via une requĂȘte GET
    const getClub = async () => {
        await axios
            .get(`http://127.0.0.1:8000/api/clubs/${club}`)
            .then(res => {
                setNameClub(res.data.nameClub); // Stocke le nom du club dans l'état
            })
            .catch(error => {
                console.log(error); // Affichage des erreurs dans la console pour debug
            });
    };

    // Gestionnaire de changement pour le fichier du logo
    const changeHandler = (event) => {
        setLogoClub(event.target.files[0]); // Stocke le fichier sélectionné
    };

    // Fonction pour mettre Ă  jour le club via une requĂȘte PATCH
    const updateClub = async (e) => {
        e.preventDefault(); // EmpĂȘche le rechargement de la page lors de la soumission

        // Création d'un objet FormData pour envoyer les données avec le fichier
        const formData = new FormData();
        formData.append('_method', 'PATCH'); // Méthode HTTP pour mettre à jour les données
        formData.append("nameClub", nameClub);

        // Vérifie si un logo a été sélectionné avant de l'envoyer
        if (logoClub !== null) {
            formData.append("logoClub", logoClub);
        }

        // Envoi de la requĂȘte PATCH pour mettre Ă  jour les informations du club
        await axios
            .post(`http://127.0.0.1:8000/api/clubs/${club}`, formData)
            .then(() => navigate("/clubs")) // Redirection vers la liste des clubs aprĂšs modification
            .catch(({ response }) => {
                if (response.status === 422) {
                    setValidationError(response.data.errors); // Stocke les erreurs de validation
                }
            });
    };

    return (
        <div>
            {/* Affichage du menu de navigation */}
            <Menu />

            <div className="container mt-5">
                <div className="row justify-content-center">
                    <div className="col-12 col-sm-12 col-md-6">
                        <div className="card">
                            <div className="card-body">
                                <h4 className="card-title">Modifier un club</h4>
                                <hr />

                                <div className="form-wrapper">
                                    {/* Affichage des erreurs de validation si elles existent */}
                                    {Object.keys(validationError).length > 0 && (
                                        <div className="row">
                                            <div className="col-12">
                                                <div className="alert alert-danger">
                                                    <ul className="mb-0">
                                                        {Object.entries(validationError).map(
                                                            ([key, value]) => (
                                                                <li key={key}>{value}</li>
                                                            )
                                                        )}
                                                    </ul>
                                                </div>
                                            </div>
                                        </div>
                                    )}

                                    {/* Formulaire de modification d'un club */}
                                    <Form onSubmit={updateClub}>
                                        <Row>
                                            <Col>
                                                <Form.Group controlId="Name">
                                                    <Form.Label>Nom du club</Form.Label>
                                                    <Form.Control
                                                        type="text"
                                                        value={nameClub}
                                                        onChange={(event) => setNameClub(event.target.value)}
                                                    />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        <Row>
                                            <Col>
                                                <Form.Group controlId="Logo" className="mb-3">
                                                    <Form.Label>Logo</Form.Label>
                                                    <Form.Control type="file" onChange={changeHandler} />
                                                </Form.Group>
                                            </Col>
                                        </Row>

                                        {/* Bouton de soumission du formulaire */}
                                        <Button
                                            variant="primary"
                                            className="mt-2"
                                            size="lg"
                                            block="block"
                                            type="submit"
                                        >
                                            Modifier
                                        </Button>
                                    </Form>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

// Exportation du composant EditClub pour ĂȘtre utilisĂ© ailleurs dans l'application
export default EditClub;

 

 

 

 

 

par

DéveloppementSystÚmes & Réseaux
DĂ©ploiement Ă©tape par Ă©tape d’une application web sur O2Switch

DĂ©ploiement Ă©tape par Ă©tape d’une application web sur O2Switch

Je vais vous expliquer de façon dĂ©taillĂ©e comment dĂ©ployer votre application dĂ©veloppĂ©e localement (Laravel 11 + React 19 + Axios + MySQL + Bootstrap) sur un hĂ©bergement O2Switch. Suivez ces Ă©tapes dans l'ordre pour un dĂ©ploiement rĂ©ussi. Étape 1: PrĂ©paration de...