window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(function () { var w = finestra if (w.LeadBooster) { console.warn('LeadBooster esiste già') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Visibilità dei componenti in React con rendering condizionale e protezioni - The Codest
The Codest
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Industrie
    • Fintech e banche
    • E-commerce
    • Adtech
    • Tecnologia della salute
    • Produzione
    • Logistica
    • Automotive
    • IOT
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
  • Chi siamo
  • Servizi
    • Sviluppo di software
      • Sviluppo Frontend
      • Sviluppo backend
    • Staff Augmentation
      • Sviluppatori Frontend
      • Sviluppatori backend
      • Ingegneri dei dati
      • Ingegneri del cloud
      • Ingegneri QA
      • Altro
    • Consulenza
      • Audit e consulenza
  • Valore per
    • CEO
    • CTO
    • Responsabile della consegna
  • Il nostro team
  • Case Studies
  • Sapere come
    • Blog
    • Incontri
    • Webinar
    • Risorse
Carriera Contattate
Freccia indietro TORNA INDIETRO
2023-05-19
Sviluppo di software

Visibilità dei componenti in React con rendering condizionato e protezioni

Bartlomiej Kuczynski

Scoprite come semplificare e migliorare la visibilità dei componenti in React utilizzando il rendering condizionale e i componenti di protezione.

Oggi vorrei parlare di come controllare visibilità dei componenti in React. Ma prima di iniziare c'è una piccola
esclusione di responsabilità:

La soluzione presentata non è molto sicura nel senso di proteggere l'applicazione dagli "hacker" (chiunque essi siano).
Ricordate che è necessario proteggere gli endpoint e utilizzare buone pratiche nella progettazione delle applicazioni. Questa soluzione
rende il vostro lavoro un po' più facile.

Compito, soluzione del problema o obiettivo che si vuole raggiungere

Una delle funzionalità più comuni è quella di mostrare il componente solo per un gruppo di utenti che hanno alcuni diritti specifici,
ruoli o privilegi. La soluzione più comune è quella di aggiungere alcuni ses a codice, controllare manualmente le condizioni e mostrare o meno gli elementi.

Diamo un'occhiata a Intestazione dell'applicazione semplice che contiene pochi elementi di navigazione.

<!-- wp:paragraph -->
<p><code>dattiloscritto jsx<br>
export const SimpleAppHeader: FC = () =&gt; {<br>
    return (<br>
        <header><br>
            <nav><br>
                <ul><br>
                    {<br>
                        currentUser.role === "ADMIN" &amp;&amp;<br>
                        <li>Componente solo ADMIN</li><br>
                    }<br>
                    {<br>
                        currentUser.role === "USER" &amp;&amp;<br>
                        <li>Componente solo utente</li><br>
                    }<br>
                    {<br>
                        (currentUser.role === "ADMIN" || currentUser.role === "USER") &amp;&amp;<br>
                        <li>Componente solo amministratore e utente</li><br>
                    }<br>
                    <li>Elemento di uso generale</li><br>
                </ul><br>
            </nav><br>
        </header><br>
    )<br>
}<br>
</code></p>
<!-- /wp:paragraph -->

Sembra "non male". Probabilmente si potrebbero incapsulare i controlli in funzioni per ridurre la complessità. utente corrente è un oggetto
che ha ruolo ma può essere qualsiasi cosa che si voglia utilizzare come oggetto del nostro meccanismo di controllo.

Questo codice presenta alcuni problemi. Se progetto cresce, probabilmente usiamo queste costruzioni in molti luoghi. Quindi dobbiamo copiare,
in qualche modo, le condizioni. Questo codice è difficile da mantenere e da modificare in futuro. Soprattutto quando le regole di accesso cambiano durante
tempo, ad esempio, dobbiamo cambiare utente corrente in qualcos'altro. È molto difficile da testare. È necessario scrivere molti test
solo per verificare se le condizioni sono corrette.

Semplificazione

È ora di semplificare un po' questo codice. Possiamo estrarre alcuni metodi e rendere il codice più breve e meno complesso:

const isAdmin = (role: string): booleano => role === "ADMIN";
const isUser = (role: string): booleano => role === "USER";
const isAdminOrUser = (role: string): booleano => isAdmin(role) || isUser(role);

export const SimplifiedAppHeader: FC = () => {
return (

{

isAdmin(currentUser.role) &&
Componente solo amministratore

}
{
isUser(currentUser.role) &&

Componente solo utente

}
{
(isAdminOrUser(currentUser.role)) &&

Componente solo Admin e Utente

}

Elemento di uso generale

)
}
```

Sembra promettente. Riduciamo il rumore e le linee ripetute. Il codice è più leggibile e più facile da mantenere. Ma date un'occhiata a
funzione isAdminOrUser. Abbiamo solo due ruoli. Se introduciamo un terzo ruolo, dobbiamo creare un altro insieme di funzioni
che combina i ruoli. È tempo di un'altra versione.

Filtraggio

Introduciamo la funzione haRuolo che sostituirà il nostro èX funzioni.

const hasRole = (role: string, requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => role === s);
return found !== undefined;
}

export const FilteringAppHeader: FC = () => {
return (

{

hasRole(currentUser.role, ["ADMIN"]) &&
Componente solo amministratore

}
{
hasRole(currentUser.role, ["USER"]) &&

Componente solo utente

}
{
hasRole(currentUser.role, ["ADMIN", "USER"]) &&

Componente solo per amministratori e utenti

}

Elemento di uso generale

)
}
```

Ora sembra buono. Abbiamo ancora delle condizioni nella parte html del codice, ma ora possiamo testare haRuolo funzione e la fiducia che essa
verrà utilizzato con l'insieme corretto di parametri. L'aggiunta o la modifica dei ruoli è ora più semplice. Utilizziamo un array che contiene tutti i ruoli
ruoli di cui abbiamo bisogno.

Tuttavia, questa soluzione è vincolata a utente corrente oggetto. Il presupposto è che l'oggetto sia in qualche modo globale o facilmente accessibile in
in qualsiasi punto dell'applicazione. Quindi possiamo provare a incapsulare questo aspetto. Naturalmente, possiamo spostarlo in haRuolo funzione:

 const hasRole = (requiredRole: string[]): boolean => {
     let found: string | undefined = requiredRole.find(s => currentUser.role === s);
     return found !== undefined;
 }

Ma questo non ci dà quasi nulla.

Il Guardia Componente

È ora di creare un componente che incapsuli l'intera logica. L'ho chiamato Guardia e questo è il modo in cui voglio usarlo.

 export const GuardedAppHeader: FC = () => {
     return (
         
  • Componente per soli amministratori
  • Componente solo utente
  • Componente amministratore e utente
  • Elemento di uso generale
); }

Il componente ha bisogno di due proprietà. La prima bambini responsabile dei contenuti protetti. Secondo ruoli richiesti che
gestire una serie di ruoli che ci danno accesso.

Abbiamo bisogno di una rappresentazione di questa struttura. È molto semplice. Estendiamo il tipo React.PropsConBambini che ha bambini
proprietà. Naturalmente, è possibile aggiungere manualmente questa proprietà al tipo e omettere l'estensione.

interfaccia IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
}

Anche il componente in sé è semplice. Riutilizzeremo haRuolo funzione qui.

export const Guard = (props: IGuardProps) => {
const hasRole = (requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => currentUser.role === s);
return found !== undefined;
}

if (hasRole(props.requiredRoles)) {
    return (
        
            {props.children}
        
    );
} else {
    restituisce ;
}
}
"`

Potrei dire di fermarsi qui, ma sarebbe troppo facile. Ora abbiamo un componente, e possiamo usarlo fino all'estremo 😀

`GuardService`

Il primo passo sarà l'esternalizzazione dei controlli. utente corrente è un valore codificato. Vorrei incapsulare questo valore
in qualche servizio che "saprà" come verificare i ruoli. Tecnicamente questo significa che spostiamo haRuolo ad un'altra funzione
classe.

Creo un'interfaccia semplice IGuardService che ha solo una proprietà - haRuolo.

Esportare l'interfaccia IGuardService {
checkRole: (roles: string[]) => boolean;
}

Una semplice implementazione potrebbe essere la seguente

classe SimpleGuard implementa IGuardService {
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== undefined;
}
}

Per utilizzarlo è necessario modificare IGuardProperties e caso d'uso.

Esportare l'interfaccia IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
}

// ...

const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (

Componente solo per l'amministratore
 

Componente per soli utenti

Componente amministratore e utente
 
 

Elemento di utilizzo generale

 

);
}
```

Ora il componente si presenta come:

 export const Guard = (props: IGuardProps) => {
     if (props.guardService.checkRole(props.requiredRoles)) {
         return (
             
                 {props.children}
             
         );
     } else {
         restituisce ;
     }
 }
 

Molto meglio. Servizio di guardia ci separa dalla logica che controlla i ruoli. Possiamo cambiarla senza conseguenze per il nostro
componente. Il caso d'uso comune è quello di utilizzare i mock nei test e alcune implementazioni "reali" nel codice di produzione.

Elemento proibito

Il prossimo miglioramento riguarderà la gestione delle informazioni personalizzate Vietato elemento. La soluzione attuale rende l'elemento vuoto. Per prima cosa è necessario
cambiamento Oggetti IGuard aggiungendo la funzione che verrà resa per quell'elemento.

 export interface IGuardProps extends React.PropsWithChildren {
     requiredRoles: string[];
     guardService: IGuardService;
     forbidden?: () => React.ReactNode;
 }

Si tratta di una proprietà opzionale, il cui nome termina con il carattere punto interrogativo. Quindi potrebbe essere una funzione o indefinito. Abbiamo bisogno di
gestire il tutto in Guardia componente.

export const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) {
return (

{props.children}

);
} else if (props.forbidden === undefined) {
restituisce ;
} else {
return (
{props.forbidden()}

);
}
}

// ...

export const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (

Componente solo per l'amministratore
 

Componente per soli utenti

Vietato - solo il moderatore può vedere questo componente
}>
 

Componente moderatore

 

Componente amministratore e utente
 
 

Elemento di utilizzo generale

 

);
}
```

Flessibilità dei tipi

È il momento dell'ultimo grande cambiamento. La versione attuale del componente supporta solo i ruoli come stringa. Potremmo avere diverse
tipi di proprietà che si desidera controllare. Numeri o tipi personalizzati non sono niente di speciale. Aggiungerò il supporto dei generici.

Il primo passo è la modifica della IGuardService interfaccia. Le implementazioni dipendono dal tipo di valore testato. Potrebbe
essere qualsiasi cosa, quindi l'interfaccia dovrebbe gestirlo.

 export interface IGuardService {
     checkRole: (roles: ROLE[]) => boolean;
 }

Ora prende l'array di RUOLO tipo generico. La nostra semplice implementazione cambierà di poco.

 class SimpleGuard implements IGuardService {
     checkRole(roles: string[]): boolean {
         let found: string | undefined = roles.find(e => e === currentUser.role);
         return found !== undefined;
     }
 }

Abbiamo bisogno di aggiungere un parametro di tipo, ma potremmo preparare un'implementazione che supporti il parametro IRole interfaccia.

interfaccia IRole {
nome: stringa;
}

//...
class RoleGuardService implementa IGuardService {
checkRole(roles: IRole[]): boolean {
let found: IRole | undefined = roles.find(e => e === userWithRole.role);
return found !== undefined;
}
}
```

Il secondo passo consiste nel propagare questa modifica a Oggetti IGuard.

 interfaccia IGuardProps estende React.PropsWithChildren {
     requiredRoles: ROLE[];
     guardService: IGuardService;
     forbidden?: () => React.ReactNode;
 }

E rispettivamente a Guardia componente.

export const Guard = (props: IGuardProps) => {
     if (props.guardService.checkRole(props.requiredRoles)) {
         return (
             
                 {props.children}
             
         );
     } else if (props.forbidden === undefined) {
         restituisce ;
     } else {
         return (
                 {props.forbidden()}
             
         );
     }
 }

E i nostri casi d'uso

export const AppHeader: FC = () =&gt; {
     const guardService = new SimpleGuard();
     const roleService = new RoleGuardService();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<IRole&gt; requiredRoles={[{nome: "ADMIN"}]} guardService={roleService}&gt;.
                         <li>Componente solo per l'amministratore</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["USER"]} guardService={guardService}&gt;.
                         <li>Componente solo per l'utente</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["MODERATOR"]} guardService={guardService}
                                    forbidden={() =&gt; <div>Vietato - solo il moderatore può vederlo</div>}>
                         <li>Componente moderatore</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["USER", "ADMIN"]} guardService={guardService}&gt;.
                         <li>Componente amministratore e utente</li>
                     </Guard>
                     <li>Elemento di uso generale</li>
                 </ul>
             </nav>
         </header>
     );
 }

In questo esempio si utilizzano entrambe le implementazioni di IGuardservice solo a scopo illustrativo. Nei casi d'uso reali si
probabilmente ne utilizzerà solo uno.

Componenti specializzati e nesting

Il Guardia possono essere annidati. Si ricordi che gli accessi saranno risolti in ordine dalla maggior parte delle istanze esterne.

export const NestAppHeader: FC = () =&gt; {
     const guardService = new SimpleGuard();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<string&gt; requiredRoles={["USER", "ADMIN"]} guardService={guardService}&gt;.
                         <Guard<string&gt; requiredRoles={["ADMIN"]} guardService={guardService}&gt;.
                             <li>Componente solo per l'amministratore</li>
                         </Guard>
                         <Guard<string&gt; requiredRoles={["USER"]} guardService={guardService}&gt;.
                             <li>Componente solo per l'utente</li>
                         </Guard>
                         <li>Componente amministratore e utente</li>
                         <Guard<string&gt; requiredRoles={["MODERATOR"]} guardService={guardService}
                                        forbidden={() =&gt; <div>Vietato - solo il moderatore può vederlo</div>}>
                             <li>Componente moderatore</li>
                         </Guard>
                     </Guard>
                     <li>Elemento di uso generale</li>
                 </ul>
             </nav>
         </header>
     );
 }

Nell'esempio precedente Componente moderatore non potrebbe mai apparire, perché l'utente può gestire un solo ruolo. Prima Guardia limiti
ruoli a AMMINISTRAZIONE e UTENTE, quindi MODERATORE non passerà mai il primo controllo.

Possiamo costruire componenti specializzati che nascondono alcune proprietà.

export const AdminGuard = (props: Omit) => {
return 
{props.children}

}

//...
export const SpecializedAppHeader: FC = () => {
const guardService = new SimpleGuard();
return (

Componente solo per l'amministratore
 


Componente per soli utenti


Vietato - solo il moderatore può vederlo
}>

Componente Moderatore



Componente Amministratore e Utente

 

Elemento di uso generale

);
}
```

In questo caso AdminGuard predefinire AMMINISTRAZIONE ruolo. Nelle conseguenze, dobbiamo definire esplicitamente il tipo di RUOLO tipo
parametro.

Riassumere

In questo articolo vi mostrerò come creare e usare Guardia componente in React. Partiamo da un codice complesso e difficile da
leggere e mantenere. Lo facciamo evolvere in uno stato più facile per gli sviluppatori e introduciamo un componente funzionale personalizzato. Successivamente
estendere il componente aggiungendo funzionalità extra, rifattorizzare il servizio di estrazione e infine aggiungere tipi generici.

Infine, abbiamo un componente che può essere annidato e che è facile da testare e mantenere.

Articoli correlati

Sviluppo di software

Pro e contro dell'React

Perché vale la pena utilizzare la libreria React? Quali vantaggi offre questa libreria JavaScript? Per trovare le risposte, immergetevi in questo articolo e scoprite i reali vantaggi dell'uso dell'React.

The Codest
Cezary Goralski Software Engineer

Iscrivetevi alla nostra knowledge base e rimanete aggiornati sulle competenze del settore IT.

    Chi siamo

    The Codest - Società internazionale di sviluppo software con centri tecnologici in Polonia.

    Regno Unito - Sede centrale

    • Ufficio 303B, 182-184 High Street North E6 2JA
      Londra, Inghilterra

    Polonia - Poli tecnologici locali

    • Parco uffici Fabryczna, Aleja
      Pokoju 18, 31-564 Cracovia
    • Ambasciata del cervello, Konstruktorska
      11, 02-673 Varsavia, Polonia

      The Codest

    • Casa
    • Chi siamo
    • Servizi
    • Case Studies
    • Sapere come
    • Carriera
    • Dizionario

      Servizi

    • Consulenza
    • Sviluppo di software
    • Sviluppo backend
    • Sviluppo Frontend
    • Staff Augmentation
    • Sviluppatori backend
    • Ingegneri del cloud
    • Ingegneri dei dati
    • Altro
    • Ingegneri QA

      Risorse

    • Fatti e miti sulla collaborazione con un partner esterno per lo sviluppo di software
    • Dagli Stati Uniti all'Europa: Perché le startup americane decidono di trasferirsi in Europa
    • Confronto tra gli hub di sviluppo Tech Offshore: Tech Offshore Europa (Polonia), ASEAN (Filippine), Eurasia (Turchia)
    • Quali sono le principali sfide di CTO e CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Condizioni di utilizzo del sito web

    Copyright © 2025 di The Codest. Tutti i diritti riservati.

    it_ITItalian
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek it_ITItalian