📐 Construire une app en JS
24 Composants

Les composants

Notre page comporte 2 composants React :

function HomePage() {
    const {accomodations, loading} = useAccomodations()
    return (<Layout loading={loading}>
        {accomodations.map(accomodation => <Accomodation 
                accomodation={accomodation} 
                onBook={() => action()}
            >)}
    </Layout>)
}

Nous avons séparé la logique d'animation dans une fonction useAccomodations. Ainsi, nos composants sont centrés sur 1 seule reponsabilité : l'affichage.

Rôles de nos 2 composants

Le principe de React est la composition. On imbrique des composants dans une structure déclarative pour représenter l'interface graphique attendue.

Le rôle de notre composant Layout est de s'occuper de la disposition générale des éléments de la page.

Et celui de notre composant Accomodation est d'afficher la carte d'un logement de vacances que l'utilisateur peut réserver.

L'échéance de votre démo approche. Et vous n'avez pas le temps de peaufiner le rendu graphique. Alors prenons un raccourci, qui fait désormais le quotidien de tous les développeurs.

Un raccourci

Utilisons ChatGPT pour créer ces 2 composants React.

Voici le prompt :

Ecris le code des composants React Layout et Accomodation pour ma web application de réservation de logements de vacances : 
function HomePage() {
    const {accomodations, loading} = useAccomodations()
    return (<Layout loading={loading}>
        {accomodations.map(accomodation => <Accomodation 
                accomodation={accomodation} 
                onBook={() => action()}
            >)}
    </Layout>)
}

Le résultat est minimaliste. Et surtout pas très beau.

Alors améliorons cela en ajoutant un screenshot d'un site bien connu :

Améliore les composants pour que ça ressemble à ça

Un joli screenshot.

Et là, nous avons bien mieux !

Le Layout possède un bandeau de recherche, qui va nous être utile.

import React from 'react';
import './Layout.css';
 
function Layout({ children, loading }) {
    return (
        <div className="layout">
            <header className="header">
                <div className="search-bar">
                    <input type="text" placeholder="Rechercher une destination" />
                    <input type="text" placeholder="Arrivée" />
                    <input type="text" placeholder="Départ" />
                    <input type="text" placeholder="Ajouter des voyageurs" />
                    <button className="search-button">🔍</button>
                </div>
            </header>
            <main className="main-content">
                {loading ? (
                    <div className="loading">Loading...</div>
                ) : (
                    <div className="accommodations-list">{children}</div>
                )}
            </main>
        </div>
    );
}
 
export { Layout };

Et le composant Accomodation comporte notre bouton de réservation.

import React from 'react';
import './Accomodation.css';
 
function Accomodation({ accomodation, onBook }) {
    return (
        <div className="accomodation-card">
            <img src={accomodation.imageUrl} alt={accomodation.name} className="accomodation-image" />
            <div className="accomodation-details">
                <div className="accomodation-header">
                    <h2>{accomodation.location}</h2>
                    <button className="favorite-button">❤️</button>
                </div>
                <p className="accomodation-name">{accomodation.name}</p>
                <p className="accomodation-dates">{accomodation.dates}</p>
                <p className="accomodation-host">{accomodation.host}</p>
                <p className="accomodation-price">{accomodation.price} € par nuit</p>
                <button className="book-button" onClick={onBook}>Réserver</button>
            </div>
        </div>
    );
}
 
export { Accomodation };

Utilisons ces 2 composants pour voir ce que ça donne.

Notre repository de test

Il reste un problème pour notre démo : nous n'avons pas de listing de logements à louer.

Rappelons-nous de notre dépendance MemoryBookingRepository :

export class MemoryBookingRepository {
  _bookings = [];
  _accomodations = [{ id: "accomodation-1" }, { id: "accomodation-2" }];
  ...
}

Il ne comporte que les 2 identifiants des logements, car nous n'avions besoin de rien de plus.

Etoffons un peu cela avec un fichier fakeAccomodations.js

export const fakeAccomodations = [
    {id: "accomodation-1", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
    {id: "accomodation-2", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
    {id: "accomodation-3", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
    {id: "accomodation-4", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
    {id: "accomodation-5", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
    {id: "accomodation-6", name: "Villa 6 pièces en Provence", imageUrl: "https://picsum.photos/200/300", location: "Saint-Rémi", host: "John Holydays", price: 230 },
]

Et injectons cela dans notre repository de test :

export class MemoryBookingRepository {
  _bookings = [];
  _accomodations = fakeAccomodations;
  ...
}

Il nous faut aussi ajouter une fonction à notre repository pour récupérer la liste des logements.

export class MemoryBookingRepository {
  _bookings = [];
  _accomodations = fakeAccomodations;
  ...
  async getAccomodations() { return this._accomodations};
}

L'aperçu de notre première page

Et le résultat n'est pas si mal !

La home page de notre clone booking

Le code complet de cette étape est disponible ici (opens in a new tab).