The Codest
  • O nás
  • Služby
    • Vývoj softwaru
      • Vývoj frontendů
      • Vývoj backendu
    • Staff Augmentation
      • Vývojáři frontendů
      • Vývojáři backendu
      • Datoví inženýři
      • Cloudoví inženýři
      • Inženýři QA
      • Další
    • To Advisory
      • Audit a poradenství
  • Odvětví
    • Fintech a bankovnictví
    • E-commerce
    • Adtech
    • Healthtech
    • Výroba
    • Logistika
    • Automobilový průmysl
    • IOT
  • Hodnota za
    • CEO
    • CTO
    • Manažer dodávek
  • Náš tým
  • Case Studies
  • Vědět jak
    • Blog
    • Setkání
    • Webové semináře
    • Zdroje
Kariéra Spojte se s námi
  • O nás
  • Služby
    • Vývoj softwaru
      • Vývoj frontendů
      • Vývoj backendu
    • Staff Augmentation
      • Vývojáři frontendů
      • Vývojáři backendu
      • Datoví inženýři
      • Cloudoví inženýři
      • Inženýři QA
      • Další
    • To Advisory
      • Audit a poradenství
  • Hodnota za
    • CEO
    • CTO
    • Manažer dodávek
  • Náš tým
  • Case Studies
  • Vědět jak
    • Blog
    • Setkání
    • Webové semináře
    • Zdroje
Kariéra Spojte se s námi
Šipka zpět ZPĚT
2023-05-19
Vývoj softwaru

Viditelnost komponent v React s podmíněným vykreslováním a ochranami

Bartlomiej Kuczynski

Zjistěte, jak zjednodušit a zlepšit viditelnost komponent v React pomocí podmíněného vykreslování a ochranných komponent.

Dnes bych se rád věnoval tomu, jak ovládat viditelnost komponent v React. Ale než začneme, je tu malá
zřeknutí se odpovědnosti:

Prezentované řešení není příliš bezpečné ve smyslu ochrany aplikace před "hackery" (ať už jsou to kdokoli).
Nezapomeňte, že je třeba chránit koncové body a používat správné postupy při návrhu aplikace. Toto řešení pouze
vám jen trochu usnadní práci.

Úkol, řešení problému nebo čeho bychom chtěli dosáhnout

Jednou z nejběžnějších funkcí je zobrazování komponent pouze pro skupinu uživatelů, kteří mají určitá práva,
role nebo oprávnění. Běžným řešením je přidání některých pokuds na kód, ručně zkontrolovat podmínky a zobrazit nebo nezobrazit prvky.

Podívejme se na SimpleAppHeader komponentu, která obsahuje několik navigačních prvků.

<!-- wp:paragraph -->
<p><code>typescript jsx<br>
export const SimpleAppHeader: FC = () =&gt; {<br>
    return (<br>
        <header><br>
            <nav><br>
                <ul><br>
                    {<br>
                        currentUser.role === "ADMIN" &amp;&amp;<br>
                        <li>Pouze komponentaAdmin</li><br>
                    }<br>
                    {<br>
                        currentUser.role === "USER" &amp;&amp;<br>
                        <li>Pouze uživatelská komponenta</li><br>
                    }<br>
                    {<br>
                        (currentUser.role === "ADMIN" || currentUser.role === "USER") &amp;&amp;<br>
                        <li>Složka pouze pro administrátory a uživatele</li><br>
                    }<br>
                    <li>Prvek pro obecné použití</li><br>
                </ul><br>
            </nav><br>
        </header><br>
    )<br>
}<br>
</code></p>
<!-- /wp:paragraph -->

Nevypadá "špatně". Pravděpodobně byste mohli zapouzdřit kontroly do funkcí, abyste snížili složitost. currentUser je nějaký objekt
která má role ale může to být cokoli, co bychom chtěli použít jako předmět našeho kontrolního mechanismu.

Tento kód má některé problémy. Pokud projekt roste pravděpodobně používáme tyto konstrukce na mnoha místech. Musíme tedy kopírovat,
nějakým způsobem, podmínky. Tento kód je obtížné udržovat a v budoucnu měnit. Zvláště když se pravidla přístupu mění v průběhu
čas, např. musíme změnit currentUser do něčeho jiného. Je velmi těžké to otestovat. Musíte napsat mnoho testů
jen pro ověření, zda je váš stav v pořádku.

Zjednodušení

Je čas tento kód trochu zjednodušit. Mohli bychom z něj vyjmout některé metody a kód zkrátit a zkomplikovat:

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) &&
Pouze komponenta Admin

}
{
isUser(currentUser.role) &&

Pouze komponenta User

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

Pouze komponenta Admin a User

}

Prvek pro obecné použití

)
}
```

Vypadá to slibně. Snižujeme šum od opakovaných řádků. Kód je čitelnější a snadněji se udržuje. Ale podívejte se na
funkce isAdminOrUser. Máme pouze dvě role. Pokud zavedeme třetí roli, musíme vytvořit další sadu funkcí.
která kombinuje role. Čas na další verzi.

Filtrování

Zavedeme funkci hasRole která bude náhradou za naši isX funkce.

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"]) &&
Pouze komponenta Admin

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

Pouze komponenta User

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

Pouze komponenta Admin a User

}

Prvek pro obecné použití

)
}
```

Nyní vypadá dobře. Stále máme podmínky v html části kódu, ale nyní můžeme testovat hasRole funkci a důvěru, že
se použije se správnou sadou parametrů. Přidávání nebo změna rolí je nyní jednodušší. Používáme pole, které obsahuje všechny
role, které potřebujeme.

Toto řešení je však vázáno na currentUser objekt. Předpokladem je, že objekt je nějakým způsobem globální nebo snadno přístupný v
libovolné místo v aplikaci. Můžeme se tedy pokusit o zapouzdření. Samozřejmě ji můžeme přesunout do hasRole funkce:

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

Ale to dává nás téměř nic.

Na stránkách Strážce Komponenta

Je čas vytvořit komponentu, která zapouzdří celou logiku. Pojmenoval jsem ji Strážce a chci ho použít takto.

 export const GuardedAppHeader: FC = () => {
     return (
         
  • Komponenta pouze pro administrátory
  • Pouze uživatelská komponenta
  • Komponenta pro uživatele a administrátora
  • Prvek pro obecné použití
); }

Komponenta potřebuje dvě vlastnosti. První děti zodpovědný za obsah, který je střežen. Druhá stránka requiredRoles že
zpracovávat pole rolí, které nám poskytuje přístup.

Potřebujeme zastoupení této struktury. Je to velmi jednoduché. Rozšíříme typ React.PropsWithChildren (Rekvizity s dětmi) která má děti
nemovitosti. Tuto vlastnost můžete samozřejmě přidat do typu ručně a příponu vynechat.

rozhraní IGuardProps rozšiřuje React.PropsWithChildren {
requiredRoles: string[];
}

Samotná komponenta je také jednoduchá. Znovu použijeme hasRole zde.

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 {
    return ;
}
}
"`

A já bych mohl říct, že tady přestanu, ale bylo by to příliš snadné. Teď máme komponentu a můžeme ji využít do krajnosti 😀.

`GuardService`

Prvním krokem bude externalizace kontrol. currentUser je pevně zadaná hodnota. Rád bych tuto hodnotu zapouzdřil
do nějaké služby, která bude "umět" ověřovat role. Technicky to znamená, že přesuneme hasRole na jinou funkci
třída.

Vytvářím jednoduché rozhraní IGuardService která má pouze jednu vlastnost - hasRole.

export rozhraní IGuardService {
checkRole: (roles: string[]) => boolean;
}

Jednoduchá implementace by nyní mohla vypadat takto

třída SimpleGuard implementuje IGuardService {
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== undefined;
}
}

Abychom ji mohli používat, musíme změnit IGuardProperties a případ použití.

export rozhraní IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
}

// ...

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

Komponenta pouze pro správce
 

Komponenta pouze pro uživatele

Komponenta pro správce a uživatele
 
 

Prvek obecného použití

 

);
}
```

Nyní komponenta vypadá takto:

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

Mnohem lepší. GuardService nás oddělit od logiky, která kontroluje role. Můžeme ji změnit bez následků pro naši
součást. Běžným případem použití je použití makety v testech a "skutečné" implementace v produkčním kódu.

Zakázaný prvek

Dalším vylepšením bude manipulace s vlastními Zakázané prvek. Současné řešení vykresluje prázdný prvek. Nejprve musíme
změna IGuardProps přidání funkce, která bude tento prvek vykreslovat.

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

Jedná se o nepovinnou vlastnost, název končí otazníkem. Může to tedy být funkce nebo neurčeno. Musíme
zpracovávat v Strážce součást.

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

{props.children}

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

);
}
}

// ...

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

Komponenta pouze pro správce
 

Komponenta pouze pro uživatele

Zakázáno - vidí pouze moderátor
}>
 

Moderátorská komponenta

 

Komponenta Administrátor a uživatel
 
 

Prvek obecného použití

 

);
}
```

Flexibilita typů

Čas na poslední velkou změnu. Současná verze komponenty podporuje pouze role jako řetězec. Mohli bychom mít více různých
typy majetku, které bychom chtěli zkontrolovat. Čísla nebo vlastní typy nejsou nic zvláštního. Přidám podporu generik.

Prvním krokem jsou změny v IGuardService rozhraní. Implementace bude záviset na typu testované hodnoty. Může to být
být cokoli, takže rozhraní by to mělo zvládnout.

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

Nyní je třeba pole ROLE generický typ. Naše jednoduchá implementace se trochu změní.

 třída SimpleGuard implementuje IGuardService {
     checkRole(roles: string[]): boolean {
         let found: string | undefined = roles.find(e => e === currentUser.role);
         return found !== undefined;
     }
 }

Musíme přidat parametr typu, ale mohli bychom připravit implementaci, která podporuje IRole rozhraní.

rozhraní IRole {
name: string;
}

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

Druhým krokem je propagace této změny do IGuardProps.

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

A v tomto pořadí na Strážce součást.

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

A naše případy použití

export const AppHeader: FC = () =&gt; {
     const guardService = new SimpleGuard();
     const roleService = new RoleGuardService();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<IRole&gt; requiredRoles={[{name: "ADMIN"}]} guardService={roleService}&gt;
                         <li>Komponenta pouze pro správce</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["USER"]} guardService={guardService}&gt;
                         <li>Pouze uživatelská komponenta</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["MODERATOR"]} guardService={guardService}
                                    forbidden={() =&gt; <div>Zakázáno - vidí pouze moderátor</div>}>
                         <li>Moderátorská složka</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={["USER", "ADMIN"]} guardService={guardService}&gt;
                         <li>Komponenta správce a uživatele</li>
                     </Guard>
                     <li>Prvek obecného použití</li>
                 </ul>
             </nav>
         </header>
     );
 }

V tomto příkladu používám obě implementace IGuardservice jen pro ilustraci. V reálných případech použití
pravděpodobně používat pouze jeden.

Specializované komponenty a vnoření

Na stránkách Strážce by mohly být vnořené. Jen nezapomeňte, že přístup bude řešen v pořadí od většiny externích instancí.

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>Komponenta pouze pro správce</li>
                         </Guard>
                         <Guard<string&gt; requiredRoles={["USER"]} guardService={guardService}&gt;
                             <li>Pouze uživatelská komponenta</li>
                         </Guard>
                         <li>Komponenta správce a uživatele</li>
                         <Guard<string&gt; requiredRoles={["MODERATOR"]} guardService={guardService}
                                        forbidden={() =&gt; <div>Zakázáno - vidí pouze moderátor</div>}>
                             <li>Moderátorská složka</li>
                         </Guard>
                     </Guard>
                     <li>Prvek obecného použití</li>
                 </ul>
             </nav>
         </header>
     );
 }

Ve výše uvedeném příkladu Moderátorská složka se nikdy nemohl objevit, protože uživatel může pracovat pouze s jednou rolí. První Strážce omezení
rolí na ADMIN a UŽIVATEL, takže MODERÁTOR nikdy neprojde první kontrolou.

Můžeme vytvářet specializované komponenty, které skrývají některé vlastnosti.

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

}

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

Komponenta pouze pro správce
 


Komponenta pouze pro uživatele


Zakázáno - vidí pouze moderátor
}>

Komponenta Moderátor



Komponenta Admin a User

 

Prvek obecného použití

);
}
```

V tomto případě AdminGuard předdefinovat ADMIN role. V důsledcích je třeba explicitně definovat typ ROLE typ
parametr.

Shrnutí

V tomto článku vám ukážu, jak vytvořit a používat Strážce součástka v React. Vycházíme ze složitého kódu, který je obtížné
číst a udržovat. Vyvíjíme ji do stavu, který je pro vývojáře přívětivější, a zavádíme vlastní funkční komponenty. Dále
rozšířit komponentu o další funkce, refaktorovat extrakční službu a nakonec přidat generické typy.

Konečně máme komponentu, která by mohla být vnořená, snadno se testuje a udržuje.

Související články

Vývoj softwaru

Výhody a nevýhody modelu React

Proč se vyplatí používat React? Jaké výhody má tato knihovna JavaScript? Chcete-li se dozvědět odpovědi, ponořte se do tohoto článku a zjistěte skutečné výhody používání React.

The Codest
Cezary Goralski Software Engineer

Přihlaste se k odběru naší znalostní databáze a získejte aktuální informace o odborných znalostech z oblasti IT.

    O nás

    The Codest - Mezinárodní společnost zabývající se vývojem softwaru s technologickými centry v Polsku.

    Spojené království - ústředí

    • Kancelář 303B, 182-184 High Street North E6 2JA
      Londýn, Anglie

    Polsko - Místní technologická centra

    • Kancelářský park Fabryczna, Aleja
      Pokoju 18, 31-564 Krakov
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšava, Polsko

      The Codest

    • Home
    • O nás
    • Služby
    • Case Studies
    • Vědět jak
    • Kariéra
    • Slovník

      Služby

    • To Advisory
    • Vývoj softwaru
    • Vývoj backendu
    • Vývoj frontendů
    • Staff Augmentation
    • Vývojáři backendu
    • Cloudoví inženýři
    • Datoví inženýři
    • Další
    • Inženýři QA

      Zdroje

    • Fakta a mýty o spolupráci s externím partnerem pro vývoj softwaru
    • Z USA do Evropy: Proč se americké startupy rozhodly přesídlit do Evropy?
    • Srovnání technických vývojových center v zahraničí: Tech Offshore Evropa (Polsko), ASEAN (Filipíny), Eurasie (Turecko)
    • Jaké jsou hlavní výzvy CTO a CIO?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Copyright © 2026 by The Codest. Všechna práva vyhrazena.

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