Accueil / Articles / Gérer les états d’interface utilisateur dans le monde réel avec le rendu conditionnel de React

Gérer les états d’interface utilisateur dans le monde réel avec le rendu conditionnel de React

Apprenez à créer des interfaces utilisateur pour l’authentification, les rôles, les permissions, le chargement, les erreurs et l’état vide en React à l’aide de modèles pratiques de rendu conditionnel.

2186 mots

Dans le précédent article, vous avez abordé les bases du rendu conditionnel — en utilisant des conditions simples pour indiquer à React s’il doit afficher un composant, un autre composant ou rien du tout.

Cependant, les applications du monde réel sont rarement aussi simples :

isLoggedIn ? <Dashboard /> : <Login />

Considérez un tableau de bord réel. Un utilisateur peut se trouver dans l’un de ces états :

  • Déconnecté
  • En train de se connecter
  • Connecté
  • Administrateur
  • Utilisateur ordinaire
  • Sans autorisation requise
  • En attente de la réception des données
  • Face à une erreur API
  • En train d’afficher un ensemble de résultats vide

Chacun de ces scénarios nécessite une interface utilisateur distincte. C’est précisément là que le rendu conditionnel cesse d’être un simple truc et devient un véritable outil pour structurer votre application.

Examinons comment cela se manifeste dans du code React de qualité professionnelle.

1. Affichage basé sur l’authentification

Not Logged In
      ↓
Login Page

Logged In
      ↓
Dashboard

React peut choisir entre eux sans trop d’effort :

function App() {
  const isLoggedIn = true;
return (
    <>
      {isLoggedIn ? <Dashboard /> : <Login />}
    </>
  );
}

Cependant, les applications réelles ont généralement besoin d’un troisième état : chargement, car il peut falloir un moment pour vérifier si le token de l’utilisateur est valide. Le flux s’organise alors comme suit :

Checking Authentication
        ↓
      Loading
        ↓
  Authenticated?
   ↙          ↘
 YES          NO
 ↓             ↓
Dashboard     Login

En code, cela peut se traduire par :

function App() {
  const isLoading = false;
  const isLoggedIn = true;
if (isLoading) {
    return <LoadingSpinner />;
  }
  return isLoggedIn
    ? <Dashboard />
    : <Login />;
}

Vous verrez ce même schéma se répéter dans d’innombrables applications React en production.

2. Affichage basé sur les rôles

L’authentification vous indique qui est connecté. L’autorisation vous indique ce que cette personne est autorisée à faire.

Prenons un outil de gestion des employés comme exemple. Un administrateur peut voir :

View Employees
Add Employee
Edit Employee
Delete Employee

Tandis qu’un utilisateur standard ne voit que :

View Employees

Vous pouvez afficher conditionnellement des actions en fonction du rôle de l’utilisateur :

function EmployeeCard({ userRole }) {
  return (
    <div>
      <h2>Employee Details</h2>
      <button>View</button>
      {userRole === "admin" && (
        <>
          <button>Edit</button>
          <button>Delete</button>
        </>
      )}
    </div>
  );
}

Avec cette configuration, les contrôles réservés aux administrateurs n’apparaissent que pour eux.

Remarque importante sur la sécurité

Le rendu conditionnel détermine ce qui s’affiche dans l’interface utilisateur, mais cacher un élément n’est pas un substitut à une véritable sécurité. Par exemple :

{isAdmin && <DeleteButton />}

Cela empêche un utilisateur ordinaire de voir le bouton, mais le serveur doit néanmoins vérifier indépendamment que la demande provient bien de quelqu’un autorisé à supprimer des données. Pensez-y de cette manière :

Frontend
↓
Controls what users SEE

Backend
↓
Controls what users CAN DO

N’utilisez jamais le rendu conditionnel côté client comme mécanisme d’autorisation.

3. Interface utilisateur basée sur les permissions

Les applications plus complexes ont souvent besoin d’une granularité supérieure à celle de rôles simples tels que :

Admin
User

À la place, vous pouvez définir des permissions spécifiques telles que :

CAN_VIEW_USERS
CAN_EDIT_USERS
CAN_DELETE_USERS
CAN_EXPORT_REPORT

Les composants peuvent alors afficher chaque action individuellement en fonction des permissions disponibles :

function UserActions({ permissions }) {
  return (
    <>
      {permissions.includes("CAN_EDIT_USERS") && (
        <button>Edit</button>
      )}
      {permissions.includes("CAN_DELETE_USERS") && (
        <button>Delete</button>
      )}
    </>
  );
}

Cette approche vous permet de contrôler avec beaucoup plus de précision ce que chaque utilisateur peut faire.

4. États de chargement

Supposons qu’un tableau de bord envoie une requête API qui met deux secondes à s’exécuter. Que doit apparaître à l’écran pendant cette période ? Certainement pas une page vide — vous souhaitez plutôt un indicateur de chargement :

if (loading) {
  return <p>Loading products...</p>;
}

Le flux global se présente comme suit :

API Request
    ↓
Loading = true
    ↓
Show Loader
    ↓
API Response
    ↓
Loading = false
    ↓
Show Content

Les indicateurs de chargement donnent l’impression à une application d’être réactive, même lorsque le réseau est lent.

5. Chargeurs squelette

Au lieu d’un message de texte simple comme :

Loading...

de nombreuses interfaces modernes affichent un élément de remplacement ayant la forme du contenu qui va être chargé — un chargeur squelette. Par exemple :

┌──────────────────────┐
│ █████████████        │
│ ███████              │
│ █████████████████    │
└──────────────────────┘

Lorsque les données réelles reviennent, elles remplacent le texte de remplacement :

┌──────────────────────┐
│ MacBook Air          │
│ ₹99,999              │
│ ⭐⭐⭐⭐⭐             │
└──────────────────────┘

La logique sous-jacente de React reste tout aussi simple :

return loading
  ? <ProductSkeleton />
  : <ProductCard />;

La seule véritable différence ici est l’amélioration de l’expérience utilisateur qu’elle apporte.

6. États d’erreur

Tout ne se passe pas toujours sans heurt avec les appels API.

La connexion peut être interrompue.

Le serveur peut planter.

Une requête peut expirer.

Au lieu de laisser votre application planter ou figer, vous devriez afficher un état d’erreur à la place.

if (error) {
  return (
    <div>
      <h2>Something went wrong.</h2>
      <button>Try Again</button>
    </div>
  );
}

7. Chargement + Erreur + Succès

Dans la pratique, ces trois états apparaissent presque toujours ensemble.

function ProductList({
  loading,
  error,
  products
}) {
      if (loading) {
    return <p>Loading...</p>;
      }
  if (error) {
    return <p>Something went wrong.</p>;
      }
  return <Products products={products} />;
     }

Vous pouvez vous représenter le flux de cette manière :

Request
   │
   ├── Loading → Loader
   │
   ├── Failed → Error
   │
   └── Success → Data

Lorsque vous aborderez les appels API et useEffect plus tard dans cette série, vous verrez ce même schéma réapparaître à plusieurs reprises.

8. États vides

Le fait qu’une requête réussisse ne garantit pas pour autant l’existence de données réelles à afficher.

Imaginons qu’un utilisateur cherche quelque chose comme :

"React Quantum Pizza Developer"

L’appel API lui-même s’effectue sans aucun erreur.

Mais le résultat peut ressembler à ceci :

products.length === 0

Plutôt que de laisser l’écran vide, donnez à l’utilisateur quelque chose d’utile à voir.

if (products.length === 0) {
  return (
    <div>
      <h2>No Products Found</h2>
      <p>Try changing your search.</p>
    </div>
  );
}

Les états vides sont très importants pour une expérience utilisateur soignée.

Chargement, état vide et erreur

Les nouveaux développeurs React confondent souvent ces trois cas, mais ils représentent des situations très différentes.

LOADING
Data hasn't arrived yet.

EMPTY
Data arrived, but nothing exists.

ERROR
Something failed.

Une application solide gère chacun de ces trois cas séparément.

9. Plusieurs conditions

Parfois, ce que vous affichez dépend de plusieurs conditions combinées.

Considérez ce flux :

Is User Logged In?
        ↓
Is Subscription Active?
        ↓
Is User Admin?
        ↓
Show Admin Dashboard

C’est tentant de regrouper tout cela en un seul énorme ternaire imbriqué :

condition1
  ? condition2
    ? condition3
      ? <A />
      : <B />
    : <C />
  : <D />

Il se compile sans problème.

Mais il est difficile à lire.

Une meilleure approche consiste à présenter clairement chaque condition séparément.

if (!isLoggedIn) {
  return <Login />;
}

if (!hasSubscription) {
  return <UpgradePlan />;
}

if (isAdmin) {
  return <AdminDashboard />;
}

return <UserDashboard />;

Cette version est bien plus facile à suivre.

10. Clauses de protection

Le schéma que vous venez de voir a un nom : les clauses de protection, également appelées retours anticipés.

Au lieu d’imbriquer des conditions les unes dans les autres :

if
 └── if
      └── if
           └── UI

gérez d’abord les cas limites et retournez rapidement.

if (loading) return <Loader />;
if (error) return <ErrorPage />;
if (!user) return <Login />;
return <Dashboard />;

Le résultat est clair.

C’est lisible.

Et c’est beaucoup plus facile à déboguer.

Pensez comme un développeur React

« Quels sont tous les états possibles dans lesquels cet écran pourrait se trouver ? »

Pour une page générée par une appel API, cette liste pourrait ressembler à ceci :

Loading
Error
Empty
Success

Pour un flux d’authentification, elle pourrait ressembler à ceci :

Logged Out
Checking Authentication
Logged In
Unauthorized

Définir ces états avant de commencer à coder rend la composante finale bien plus facile à comprendre.

Erreurs courantes chez les débutants

Enchaînement excessif de ternaires imbriqués

Ne sacrifiez pas la lisibilité juste pour économiser quelques lignes de code.

Omission de l’état vide

Un API qui renvoie un tableau vide n’est pas identique à une erreur — traitez-le comme un cas distinct.

Mélange entre masquage de l’interface et sécurité réelle

Masquer quelque chose comme :

<DeleteButton />

n’empêche en rien quelqu’un d’accéder directement à votre point de terminaison API.

L’autorisation réelle doit être gérée côté backend.

Laisser && afficher le mauvais élément

Faites attention aux codes tels que :

{items.length && <ProductList />}

Si items.length vaut par hasard 0, React peut finir par afficher :

0

directement sur la page.

La version plus sûre est :

{items.length > 0 && <ProductList />}

Désormais, la condition évalue bien à une valeur booléenne.

Bonnes pratiques

La lisibilité doit toujours primer dans le rendu conditionnel.

Préférez des schémas tels que :

if (loading) return <Loader />;

plutôt que d’accumuler des conditions à l’intérieur de JSX profondément imbriqués.

Pour les états que vous affichez fréquemment, placez-les dans des composants réutilisables distincts :

<Loader />
<ErrorMessage />
<EmptyState />

À mesure que les composants deviennent plus complexes, séparez la logique métier de ce qui est réellement affiché.

Et ne vous concentrez pas uniquement sur le scénario idéal — prévoyez tous les états dans lesquels l’interface peut réellement se trouver.

Mini-projet : Tableau de bord intelligent

Pour s’entraîner, essayez de créer un tableau de bord qui gère des cas tels que :

User Not Logged In
        ↓
Login ScreenUser

    Logged In
        ↓
Loading Dashboard
        ↓
 ┌──────┴──────┐
Error          Success
 ↓                ↓
Error UI       Data Exists?
               ↙       ↘
             YES        NO
              ↓          ↓
          Dashboard   Empty State

Ensuite, ajoutez des comportements basés sur les rôles par-dessus :

Admin
↓
Edit + Delete

User
↓
View Only

Un projet de ce type réunit plusieurs concepts en même temps :

  • Props
  • État
  • Événements
  • Rendu conditionnel

C’est exactement ainsi que les différentes composantes de React commencent à fonctionner ensemble une fois qu’on construit quelque chose de concret.

Questions d’entretien

Qu’est-ce que le rendu conditionnel ?

C’est la pratique consistant à afficher des interfaces utilisateur différentes en fonction de l’état actuel ou des conditions de votre application.

Quelle est la différence entre && et un opérateur ternaire ?

Utilisez && lorsque vous souhaitez que quelque chose s’affiche uniquement dans le cas où la condition est vraie, sans rien montrer dans les autres cas. Utilisez une expression ternaire lorsque vous avez besoin d’un affichage distinct pour les cas où la condition est vraie et fausse.

Qu’est-ce qui compte comme état vide ?

C’est l’interface que vous affichez lorsque la requête réussit mais qu’il n’y a tout simplement pas de données à afficher.

L’affichage basé sur les rôles côté frontend suffit-il pour la sécurité ?

Non. C’est une commodité d’interface — les vérifications d’autorisation réelles doivent toujours avoir lieu côté backend.

Quel est l’avantage des retours anticipés ?

Ils réduisent le niveau de nesting, ce qui rend les composants conditionnels plus faciles à lire et à maintenir.

Points clés

Jusqu’ici, vous avez couvert l’ensemble des aspects du rendering conditionnel en React.

Le rendu conditionnel permet à votre application d’afficher l’expérience appropriée en fonction de la situation actuelle.

Mais un défi reste à relever.

Supposons qu’une API renvoie :

1,000 Products

Voudriez-vous vraiment écrire :

<Product />
<Product />
<Product />
...

mille fois séparément ?

Évidemment non.

React dispose d’une méthode bien meilleure pour gérer cela.

Dans la Partie 9A, vous apprendrez à afficher des listes en utilisant map(), et vous verrez comment un seul composant peut générer des centaines ou des milliers d’éléments UI directement à partir de vos données.

Immédiatement après, vous aborderez l’une des questions d’entretien les plus classiques en React :

Pourquoi React exige-t-il une clé?

À bientôt dans la Partie 9A — Affichage de listes et clés en React.

Lectures complémentaires

  • Construire un modèle mental pour React : Reconciliation, State et Hooks — Découvrez les principes sous-jacents aux concepts fondamentaux de React — reconciliation, composants, props, state et hooks — afin de développer une intuition plutôt que de mémoriser des API.
  • React Components 101 : Construire des éléments UI reutilisables et gérables — Comprenez pourquoi diviser l’interface utilisateur en petits composants React améliore la reproductibilité, la lisibilité et la collaboration d’équipe, puis créez votre premier composant fonctionnel.
  • Activer le soutien hors ligne dans les applications web avec Service Workers — Découvrez comment utiliser Service Workers et l’API Cache pour faire en sorte qu’un site web charge instantanément et continue de fonctionner même sans connexion Internet.
  • La vraie complexité du JavaScript moderne provient des outils et non de la langue — Cet article explique comment des fonctionnalités essentielles du JavaScript telles que async/await et le chaining optionnel simplifient le code, tandis qu’un excès d’outils et de dépendances crée une complexité inutile.
  • Développement React avec l’IA : forces réelles, limites réelles — Explique où les assistants de codage basés sur l’IA accélèrent réellement le travail avec React, où ils échouent, ainsi qu’un flux de travail pratique pour les utiliser sans nuire à la qualité du code.