Angular est-il vraiment plus compliqué que React ?

Quand on débute avec Angular, il est facile de se sentir découragé face à la multitude de concepts à assimiler. Cette complexité peut inciter à se tourner vers des frameworks comme React, qui semblent plus simples à première vue. Mais est-ce vraiment le cas ?

Abonnez-vous à notre chaîne

Pour profiter des prochaines vidéos sur Angular, abonnez-vous à la nouvelle chaîne YouTube !

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Comment utiliser useExisting dans Angular pour réutiliser des services ?

Le provider useExisting dans Angular permet de réutiliser une instance existante d'un service au lieu d'en créer une nouvelle. C'est particulièrement utile pour créer des alias de services ou étendre des fonctionnalités tout en conservant une instance unique.

Comprendre useExisting avec un exemple concret

Imaginons que vous développez une application de messagerie instantanée comme WhatsApp. Vous avez :

  1. Un service de base qui gère les messages
  2. Un service avancé qui ajoute des fonctionnalités (horodatage, statut de lecture, etc.)

Au lieu de créer deux instances séparées qui géreraient les messages indépendamment (ce qui causerait des problèmes de synchronisation), vous voulez que le service avancé utilise la même instance que le service de base.

C'est exactement ce que permet useExisting : utiliser la même instance d'un service à travers différentes interfaces.

Différences avec les autres providers

ProviderDescriptionExempleCas d'utilisationDocumentation
useClassRemplace complètement un service par une autre classe{ provide: UserService, useClass: MockUserService }Quand vous voulez une implémentation complètement différente (ex: mock pour les tests)En savoir plus
useValueFournit une valeur fixe{ provide: API_URL, useValue: 'https://api.example.com' }Pour des constantes ou des objets simples prédéfinisEn savoir plus
useFactoryCrée dynamiquement une valeur via une fonction{ provide: UserService, useFactory: () => environment.production ? new RealUserService() : new MockUserService() }Quand la valeur dépend de conditions ou nécessite une logique de créationEn savoir plus
useExistingCrée un alias vers un service existant{ provide: AbstractLogger, useExisting: ConsoleLogger }Quand vous voulez utiliser un service existant sous un autre nomEn savoir plus

Mise en pratique avec notre gestionnaire d'utilisateurs

Voici un exemple concret avec notre système de gestion d'utilisateurs :

ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './user';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class BaseUserService {
  private http = inject(HttpClient);
  
  getUsers(): Observable<User[]> {
    return this.http.get<User[]>('/api/users');
  }
}
ts
import { Injectable } from '@angular/core';
import { BaseUserService } from './base-user.service';

@Injectable({
  providedIn: 'root',
  useExisting: BaseUserService
})
export class EnhancedUserService extends BaseUserService {
  getUsersWithTimestamp(): Observable<User[]> {
    return this.getUsers().pipe(
      map(users => users.map(user => ({
        ...user,
        lastAccessed: new Date()
      })))
    );
  }
}
ts
export interface User {
    id: number;
    name: string;
    username?: string;
    email: string;
    address?: {
        street: string;
        suite: string;
        city: string;
        zipcode: string;
        geo: {
            lat: string;
            lng: string;
        }
    };
    phone?: string;
    website?: string;
    company?: {
        name: string;
        catchPhrase: string;
        bs: string;
    };
}

CONSEIL

useExisting est particulièrement utile quand vous voulez ajouter des fonctionnalités à un service existant tout en gardant une seule source de vérité pour les données.

Voici comment l'utiliser dans un composant :

ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  standalone: true,
  selector: 'app-user-list',
  imports: [CommonModule],
  template: `
    @for (user of users$ | async; track user.id) {
      <div>{{ user.name }} - Dernier accès: {{ user.lastAccessed | date }}</div>
    }
  `
})
export class UserListComponent {
  private enhancedUserService = inject(EnhancedUserService);
  users$ = this.enhancedUserService.getUsersWithTimestamp();
}

IMPORTANT

Quand vous utilisez useExisting, assurez-vous que le service de base est bien fourni quelque part dans votre application, sinon Angular ne saura pas quelle instance réutiliser.

Cas d'utilisation typiques

  1. Alias de service : Créer une interface alternative pour un service existant

    • Comme avoir différentes vues du même service selon le contexte
  2. Extension de fonctionnalités : Ajouter des fonctionnalités à un service sans le modifier

    • Comme ajouter des logs ou de la validation
  3. Migration progressive : Faciliter la transition vers une nouvelle API

    • Comme maintenir la compatibilité avec l'ancien code tout en introduisant de nouvelles fonctionnalités

Bonnes pratiques

  1. Héritage : Toujours étendre la classe du service de base pour garantir la compatibilité des types
  2. Documentation : Bien documenter la relation entre les services pour faciliter la maintenance
  3. Singleton : S'assurer que le service de base est bien configuré comme singleton (providedIn: 'root')

ASTUCE

Pour déboguer, vous pouvez vérifier que c'est bien la même instance qui est utilisée en ajoutant un identifiant unique :

ts
constructor() {
  console.log('Service ID:', Math.random());
}

Chaque mois, recevez en avant-première notre newsletter avec les dernières actualités, tutoriels, astuces et ressources Angular directement par email !