Fordele og ulemper ved React
Hvorfor er det værd at bruge React? Hvilke fordele har dette JavaScript-bibliotek? For at finde svarene skal du dykke ned i denne artikel og opdage de virkelige fordele ved at bruge React.
 
                
Lær, hvordan du kan forenkle og forbedre komponenternes synlighed i React ved hjælp af betinget gengivelse og beskyttelseselementer.
I dag vil jeg gerne diskutere, hvordan man kan kontrollere komponentens synlighed i React. Men før vi begynder, er der en lille
Ansvarsfraskrivelse:
Den præsenterede løsning er ikke særlig sikker i forhold til at beskytte din applikation mod "hackere" (hvem der så end er).
Husk, at du skal beskytte dine slutpunkter og bruge god praksis i applikationsdesign. Denne løsning gør kun
gør kun dit arbejde lidt lettere.
En af de mest almindelige funktioner er kun at vise komponenter for en række brugere, der har nogle specifikke rettigheder,
roller eller rettigheder. En almindelig løsning er at tilføje nogle hviss til Kodemanuelt kontrollere forholdene og vise eller ikke vise elementer.
Lad os tage et kig på SimpleAppHeader komponent, der indeholder få navigationselementer.
<!-- wp:paragraph -->
<p><code>typescript jsx<br>
export const SimpleAppHeader: FC = () => {<br>
    return (<br>
        <header><br>
            <nav><br>
                <ul><br>
                    {<br>
                        currentUser.role === "ADMIN" &&<br>
                        <li>Komponent kun til administrator</li><br>
                    }<br>
                    {<br>
                        currentUser.role === "USER" &&<br>
                        <li>Kun bruger-komponent</li><br>.
                    }<br>
                    {<br>
                        (currentUser.role === "ADMIN" || currentUser.role === "USER") &&<br>
                        <li>Kun administrator- og brugerkomponent</li><br>
                    }<br>
                    <li>Generel brug af elementet</li><br>
                </ul><br>
            </nav><br>
        </header><br>
    )<br>
}<br>
</code></p>
<!-- /wp:paragraph -->
Det ser "ikke dårligt" ud. Du kan sikkert indkapsle checks i funktioner for at reducere kompleksiteten. nuværende bruger er et eller andet objekt
der har rolle egenskab, men det kan være hvad som helst, som vi gerne vil bruge som genstand for vores kontrolmekanisme.
Denne kode har nogle problemer. Hvis projekt vokser, bruger vi sikkert de konstruktioner mange steder. Så vi er nødt til at kopiere,
på en eller anden måde, betingelser. Denne kode er svær at vedligeholde og ændre i fremtiden. Især når adgangsreglerne ændres i løbet af
tid f.eks. vi er nødt til at ændre nuværende bruger til noget andet. Det er meget svært at teste. Du er nødt til at skrive mange tests
bare for at tjekke, om din tilstand er ok.
Det er tid til at forenkle koden lidt. Vi kan trække nogle metoder ud og gøre koden kortere og mindre kompleks:
const isAdmin = (role: string): boolean => role === "ADMIN";
const isUser = (role: string): boolean => role === "USER";
const isAdminOrUser = (role: string): boolean => isAdmin(role) || isUser(role);
export const SimplifiedAppHeader: FC = () => {
return (
{
isAdmin(currentUser.role) &&
Kun administrator-komponent
}
{
isUser(currentUser.role) &&
Kun bruger-komponent
}
{
(isAdminOrUser(currentUser.role)) &&
Kun administrator- og brugerkomponent
}
Element til generel brug
)
}
```
Det ser lovende ud. Vi reducerer støj og gentagne linjer. Koden er mere læsbar og lettere at vedligeholde. Men tag et kig på
funktion isAdminOrUser. Vi har kun to roller. Hvis vi indfører en tredje rolle, skal vi oprette et andet sæt funktioner
der kombinerer roller. Tid til en ny version.
Lad os indføre funktionen harRolle der vil være erstatning for vores isX funktioner.
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"]) &&
Kun administrator-komponent
}
{
hasRole(currentUser.role, ["USER"]) &&
Kun bruger-komponent
}
{
hasRole(currentUser.role, ["ADMIN", "USER"]) &&.
Kun administrator- og brugerkomponent
}
Element til generel brug
)
}
```Nu ser det godt ud. Vi har stadig betingelser i html-delen af koden, men nu kan vi teste harRolle funktion og stole på, at den
vil blive brugt med det korrekte sæt parametre. Det er nu nemmere at tilføje eller ændre roller. Vi bruger et array, der indeholder alle
roller, som vi skal have på plads.
Denne løsning er dog bundet til nuværende bruger objekt. Antagelsen er, at objektet på en eller anden måde er globalt eller let at få adgang til i
et hvilket som helst sted i applikationen. Så vi kan prøve at indkapsle det. Vi kan selvfølgelig flytte det til harRolle funktion:
 const hasRole = (requiredRole: string[]): boolean => {
     let found: string | undefined = requiredRole.find(s => currentUser.role === s);
     return found !== undefined;
 }Men det giver os næsten ingenting.
Vagt KomponentTid til at skabe en komponent, der indkapsler hele logikken. Jeg navngav den Vagt og det er sådan, jeg vil bruge den.
 export const GuardedAppHeader: FC = () => {
     return (
         
             
         </header
     );
 }Komponenten har brug for to egenskaber. For det første børn ansvarlig for indhold, der er beskyttet. Den anden nødvendigeRoller at
håndterer en række roller, der giver os adgang.
Vi har brug for en repræsentation af denne struktur. Det er meget enkelt. Vi udvider typen React.PropsMedBørn der har børn
egenskab. Du kan selvfølgelig tilføje denne egenskab manuelt til din type og udelade udvidelsen.
interface IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
}Selve komponenten er også enkel. Vi vil genbruge harRolle funktion her.
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.børn}
        
    );
} ellers {
    return ;
}
}
"`Og jeg kunne sige stop her, men det ville være for nemt. Nu har vi en komponent, og vi kan bruge den til det yderste 😀.
Første skridt vil være eksternalisering af kontroller. nuværende bruger er en hardcoded værdi. Jeg vil gerne indkapsle denne værdi
til en tjeneste, der "ved", hvordan man verificerer roller. Teknisk set betyder det, at vi flytter harRolle funktion til en anden
klasse.
Jeg skaber en enkel grænseflade IGuardService der kun har én egenskab - harRolle.
export interface IGuardService {
checkRole: (roles: string[]) => boolean;
}En simpel implementering kunne se sådan ud
class SimpleGuard implementerer IGuardService {
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== undefined;
}
}For at bruge det skal vi ændre IGuardEgenskaber og anvendelse.
export interface IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
}
// ...
const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Kun administrator-komponent
 
Kun bruger-komponent
Administrator- og brugerkomponent
 
 
Element til generel brug
 
);
}
```Nu ser komponenten sådan ud:
 export const Guard = (props: IGuardProps) => {
     if (props.guardService.checkRole(props.requiredRoles)) {
         return (
             
                 {props.børn}
             
         );
     } ellers {
         return ;
     }
 }
 Meget bedre. VagtService adskiller os fra den logik, der kontrollerer rollerne. Vi kan ændre det uden konsekvenser for vores
komponent. En almindelig brugssag er at bruge mock i tests og en "rigtig" implementering i produktionskoden.
Næste forbedring bliver håndtering af brugerdefinerede Forbudt element. Den nuværende løsning gengiver et tomt element. Først er vi nødt til at
ændring IGuardProps tilføjer en funktion, der skal gengives for det pågældende element.
 export interface IGuardProps extends React.PropsWithChildren {
     requiredRoles: string[];
     guardService: IGuardService;
     forbidden?: () => React.ReactNode;
 }Dette er en valgfri egenskab, og navnet slutter med et spørgsmålstegn. Så det kan være en funktion eller udefineret. Vi er nødt til at
håndtere det i Vagt komponent.
export const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) {
return (
{props.børn}
);
} else if (props.forbidden === undefined) {
return ;
} else {
return (
{props.forbidden()}
);
}
}
// ...
export const AppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Kun administrator-komponent
 
Kun bruger-komponent
Forbudt - kun moderator kan se dette
}>
 
Moderator-komponent
 
Administrator- og brugerkomponent
 
 
Element til generel brug
 
);
}
```Tid til den sidste store ændring. Den nuværende version af komponenten understøtter kun roller som streng. Vi kunne have flere forskellige
typer af egenskaber, som vi gerne vil kontrollere. Tal eller brugerdefinerede typer er ikke noget særligt. Jeg vil tilføje generisk understøttelse.
Første skridt er ændringer i IGuardService grænseflade. Implementeringer vil afhænge af typen af den testede værdi. Det kan være
være hvad som helst, så grænsefladen bør håndtere det.
 export interface IGuardService {
     checkRole: (roles: ROLE[]) => boolean;
 }Nu tager den et array af ROLLE generisk type. Vores enkle implementering vil ændre sig lidt.
 class SimpleGuard implementerer IGuardService {
     checkRole(roles: string[]): boolean {
         let found: string | undefined = roles.find(e => e === currentUser.role);
         return found !== undefined;
     }
 }Vi er nødt til at tilføje en typeparameter, men vi kan forberede en implementering, der understøtter IRole interface.
interface IRole {
navn: streng;
}
//...
class RoleGuardService implementerer IGuardService {
checkRole(roles: IRole[]): boolean {
lad fundet: IRole | undefined = roles.find(e => e === userWithRole.role);
return found !== undefined;
}
}
```Andet trin er at udbrede denne ændring til IGuardProps.
 interface IGuardProps extends React.PropsWithChildren {
     requiredRoles: ROLE[];
     guardService: IGuardService;
     forbidden?: () => React.ReactNode;
 }Og henholdsvis til Vagt komponent.
export const Guard = (props: IGuardProps) => {
     if (props.guardService.checkRole(props.requiredRoles)) {
         return (
             
                 {props.børn}
             
         );
     } else if (props.forbidden === undefined) {
         return ;
     } else {
         return (
                 {props.forbidden()}
             
         );
     }
 }Og vores brugsscenarier
export const AppHeader: FC = () => {
     const guardService = new SimpleGuard();
     const roleService = new RoleGuardService();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<IRole> requiredRoles={[{name: "ADMIN"}]} guardService={roleService}>.
                         <li>Komponent kun for administratorer</li>
                     </Guard>
                     <Guard<string> requiredRoles={["USER"]} guardService={guardService}>.
                         <li>Komponent kun for brugere</li>
                     </Guard>
                     <Guard<string> requiredRoles={["MODERATOR"]} guardService={guardService}
                                    forbidden={() => <div>Forbudt - kun moderator kan se dette</div>}>
                         <li>Moderator-komponent</li>
                     </Guard>
                     <Guard<string> requiredRoles={["USER", "ADMIN"]} guardService={guardService}>.
                         <li>Administrator- og brugerkomponent</li>
                     </Guard>
                     <li>Generelt brugselement</li>
                 </ul>
             </nav>
         </header>
     );
 }I dette eksempel bruger jeg begge implementeringer af IGuardservice bare til illustrative formål. I rigtige brugssager skal du
bruger sandsynligvis kun én.
Den Vagt kan være indlejret. Bare husk, at adgangen vil blive løst i rækkefølge fra den mest eksterne instans.
export const NestAppHeader: FC = () => {
     const guardService = new SimpleGuard();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<string> requiredRoles={["USER", "ADMIN"]} guardService={guardService}>.
                         <Guard<string> requiredRoles={["ADMIN"]} guardService={guardService}>.
                             <li>Komponent kun for administratorer</li>
                         </Guard>
                         <Guard<string> requiredRoles={["USER"]} guardService={guardService}>.
                             <li>Komponent kun for brugere</li>
                         </Guard>
                         <li>Administrator- og brugerkomponent</li>
                         <Guard<string> requiredRoles={["MODERATOR"]} guardService={guardService}
                                        forbidden={() => <div>Forbudt - kun moderator kan se dette</div>}>
                             <li>Moderator-komponent</li>
                         </Guard>
                     </Guard>
                     <li>Generelt brugselement</li>
                 </ul>
             </nav>
         </header>
     );
 }I ovenstående eksempel Moderator-komponent kunne aldrig vises, fordi brugeren kun kan håndtere én rolle. Den første Vagt grænser
roller til ADMIN og BRUGERså MODERATOR vil aldrig bestå første kontrol.
Vi kan bygge specialiserede komponenter, der skjuler nogle egenskaber.
export const AdminGuard = (props: Omit) => {
return .
{props.children}
}
//...
export const SpecializedAppHeader: FC = () => {
const guardService = new SimpleGuard();
return (
Kun administrator-komponent
 
.
Kun bruger-komponent
Forbudt - kun moderator kan se dette
}>
Moderator-komponent
.
Administrator- og brugerkomponent
 
Element til generel brug
);
}
```I dette tilfælde AdminGuard foruddefinerer ADMIN rolle. I konsekvenserne er vi nødt til eksplicit at definere typen af ROLLE type
parameter.
I denne artikel viser jeg dig, hvordan du opretter og bruger Vagt komponent i React. Vi starter med kompleks kode, der er svær at
læse og vedligeholde. Vi udvikler den til en mere udviklervenlig tilstand og introducerer brugerdefinerede funktionelle komponenter. Dernæst
udvide komponenten med ekstra funktioner, refaktorere udtrækningstjenesten og endelig tilføje generiske typer.
Endelig har vi en komponent, der kan indlejres, og som er nem at teste og vedligeholde.
