The Codest
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Pramonės šakos
    • Fintech ir bankininkystė
    • E-commerce
    • Adtech
    • Sveikatos technologijos
    • Gamyba
    • Logistika
    • Automobiliai
    • IOT
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
  • Apie mus
  • Paslaugos
    • Programinės įrangos kūrimas
      • Priekinės dalies kūrimas
      • Galinės dalies kūrimas
    • Staff Augmentation
      • Priekinės dalies kūrėjai
      • Atgalinės versijos kūrėjai
      • Duomenų inžinieriai
      • Debesų inžinieriai
      • QA inžinieriai
      • Kita
    • Patariamoji tarnyba
      • Auditas ir konsultacijos
  • Vertė už
    • CEO
    • CTO
    • Pristatymo vadybininkas
  • Mūsų komanda
  • Case Studies
  • Sužinokite, kaip
    • Tinklaraštis
    • Susitikimai
    • Interneto seminarai
    • Ištekliai
Karjera Susisiekite su mumis
Atgal rodyklė GRĮŽTI ATGAL
2023-05-19
Programinės įrangos kūrimas

Komponentų matomumas "React" sistemoje su sąlyginiu atvaizdavimu ir apsaugomis

Bartlomiejus Kučinskis

Sužinokite, kaip supaprastinti ir pagerinti komponentų matomumą React naudojant sąlyginį atvaizdavimą ir apsauginius komponentus.

Šiandien norėčiau aptarti, kaip kontroliuoti komponento matomumas React. Bet prieš pradėdami yra mažas
Atsakomybės apribojimas:

Pateiktas sprendimas nėra labai saugus, t. y. neapsaugo jūsų programos nuo "įsilaužėlių" (kad ir kas jie būtų).
Nepamirškite, kad reikia apsaugoti savo galinius taškus ir taikyti gerąją taikomosios programos projektavimo praktiką. Šis sprendimas tik
šiek tiek palengvina jūsų darbą.

Užduotis, problemos sprendimas arba tai, ką norėtume pasiekti

Viena iš dažniausiai pasitaikančių funkcijų - rodyti komponentą tik tam tikriems naudotojams, turintiems tam tikras konkrečias teises,
vaidmenis ar privilegijas. Įprastas sprendimas - pridėti keletą jeiį kodas, rankiniu būdu tikrinti sąlygas ir rodyti arba nerodyti elementus.

Leiskite pažvelgti į SimpleAppHeader komponentas, kuriame yra keletas navigacijos elementų.

<!-- wp:paragraph -->
<p><code>typescript jsx<br>
export const SimpleAppHeader: FC = () =&gt; {<br>
    grąžinti (<br>
        <header><br>
            <nav><br>
                <ul><br>
                    {<br>
                        currentUser.role === "ADMIN" &amp;&amp;<br>
                        <li>Tik administratoriaus komponentas</li><br>
                    }<br>
                    {<br>
                        currentUser.role === "USER" &amp;&amp;<br>
                        <li>Tik naudotojo komponentas</li><br>
                    }<br>
                    {<br>
                        (currentUser.role === "ADMIN" || currentUser.role === "USER") &amp;&amp;<br>
                        <li>Tik administratoriaus ir naudotojo komponentas</li><br>
                    }<br>
                    <li>Bendrojo naudojimo elementas</li><br>
                </ul><br>
            </nav><br>
        </header><br>
    )<br>
}<br>
</code></p>
<!-- /wp:paragraph -->

Atrodo "neblogai". Tikriausiai, norint sumažinti sudėtingumą, būtų galima patikras įtraukti į funkcijas. currentUser yra tam tikras objektas
kuris turi vaidmuo savybė, tačiau tai gali būti bet kas, ką norėtume naudoti kaip kontrolės mechanizmo objektą.

Šis kodas turi tam tikrų problemų. Jei projektas auga, mes tikriausiai naudojame šias konstrukcijas daugelyje vietų. Taigi mums reikia kopijuoti,
kažkaip, sąlygos. Šį kodą sunku prižiūrėti ir ateityje keisti. Ypač kai prieigos taisyklės keičiasi
laikas, pvz., turime pakeisti currentUser į ką nors kita. Tai labai sunku patikrinti. Reikia parašyti daug testų.
tik norėdami patikrinti, ar jūsų būklė yra tinkama.

Supaprastinimas

Laikas šiek tiek supaprastinti šį kodą. Galime išskirti keletą metodų ir padaryti kodą trumpesnį ir ne tokį sudėtingą:

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) &&
Tik administratoriaus komponentas

}
{
isUser(currentUser.role) &&

Tik naudotojo komponentas

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

Tik administratoriaus ir naudotojo komponentas

}

Bendrojo naudojimo elementas

)
}
```

Atrodo daug žadantis. Mes mažiname triukšmą od pakartoti linijas. Kodas labiau skaitomas ir lengviau prižiūrimas. Tačiau pažvelkite į
funkcija isAdminOrUser. Turime tik du vaidmenis. Jei įvesime trečią vaidmenį, turėsime sukurti kitą funkcijų rinkinį.
kuris sujungia vaidmenis. Laikas kitai versijai.

Filtravimas

Įveskime funkciją hasRole kuris pakeis mūsų isX funkcijos.

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"]) &&
Tik administratoriaus komponentas

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

Tik naudotojo komponentas

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

Tik administratoriaus ir naudotojo komponentas

}

Bendrojo naudojimo elementas

)
}
```

Dabar atrodo gerai. Vis dar turime sąlygas html kodo dalyje, bet dabar galime testuoti hasRole funkcija ir pasitikėjimas, kad ji
bus naudojamas teisingas parametrų rinkinys. Dabar lengviau pridėti arba keisti vaidmenis. Naudojame masyvą, kuriame yra visi
vaidmenis, kurių mums reikia.

Tačiau šis sprendimas yra susijęs su currentUser objektas. Darytina prielaida, kad objektas yra globalus arba lengvai pasiekiamas
bet kurioje taikymo vietoje. Taigi galime pabandyti tai įkapsuliuoti. Žinoma, galime perkelti jį į hasRole funkcija:

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

Tačiau tai suteikia mus beveik nieko.

Svetainė Apsauga Komponentas

Laikas sukurti komponentą, kuris apima visą logiką. Pavadinau jį Apsauga ir noriu jį naudoti taip.

 export const GuardedAppHeader: FC = () => {
     return (
         
  • Tik administratoriaus komponentas
  • Tik naudotojo komponentas
  • Administratoriaus ir naudotojo komponentas
  • Bendrojo naudojimo elementas
); }

Komponentui reikia dviejų savybių. Pirmoji vaikai atsakingas už saugomą turinį. Antrasis requiredRoles kad
tvarkyti vaidmenų masyvą, kuris suteikia mums prieigą.

Mums reikia šios struktūros atstovavimo. Tai labai paprasta. Mes išplečiame tipą React.Rekvizitai su vaikais kuris turi vaikai
nuosavybė. Žinoma, galite rankiniu būdu pridėti šią savybę prie savo tipo ir praleisti plėtinį.

sąsaja IGuardProps plečia React.PropsWithChildren {
requiredRoles: string[];
}

Pats komponentas taip pat yra paprastas. Mes pakartotinai panaudosime hasRole funkcija čia.

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 {
    grąžinti ;
}
}
"`

Galėčiau pasakyti, kad čia reikia sustoti, bet tai būtų per daug paprasta. Dabar mes turime komponentą ir galime juo naudotis iki kraštutinumo 😀

`GuardService`

Pirmasis žingsnis - patikrinimų perkėlimas į išorę. currentUser yra kietai užkoduota reikšmė. Norėčiau šią reikšmę užkoduoti
į tam tikrą tarnybą, kuri "žinos", kaip patikrinti vaidmenis. Techniškai tai reiškia, kad mes perkeliame hasRole funkciją į kitą
klasė.

Aš kuriu paprastą sąsają IGuardService kuris turi tik vieną savybę - hasRole.

eksporto sąsaja IGuardService {
checkRole: (roles: string[]) => boolean;
}

Dabar paprastas įgyvendinimas galėtų atrodyti taip

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

Norėdami jį naudoti, turime pakeisti IGuardProperties ir naudojimo atvejis.

eksportas sąsaja IGuardProps extends React.PropsWithChildren {
requiredRoles: string[];
guardService: IGuardService;
}

// ...

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

Tik administratoriaus komponentas
 

Tik naudotojo komponentas

Administratoriaus ir naudotojo komponentas
 
 

Bendrojo naudojimo elementas

 

);
}
```

Dabar komponentas atrodo taip:

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

Daug geriau. GuardService atskirti mus nuo logikos, kuri tikrina vaidmenis. Galime ją keisti be pasekmių mūsų
komponentas. Dažniausiai bandymuose naudojamas imitacinis komponentas, o gamybiniame kode - "tikrasis".

Draudžiamas elementas

Kitas patobulinimas - pasirinktinių Draudžiama elementas. Dabartinis sprendimas atvaizduoja tuščią elementą. Pirmiausia reikia
keisti IGuardProps pridedant funkciją, kuri bus atvaizduojama tam elementui.

 eksportas sąsaja IGuardProps extends React.PropsWithChildren {
     requiredRoles: string[];
     guardService: IGuardService;
     forbidden?: () => React.ReactNode;
 }

Tai neprivaloma savybė, pavadinimas baigiasi klausimo ženklo ženklu. Taigi tai gali būti funkcija arba neapibrėžtas. Mums reikia
tvarkyti jį Apsauga komponentas.

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

{props.children}

);
} else if (props.forbidden === undefined) {
grąžinti ;
} else {
grąžinti (
{props.forbidden()}

);
}
}

// ...

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

Tik administratoriaus komponentas
 

Tik naudotojo komponentas

Draudžiama - tai gali matyti tik moderatorius
}>
 

Moderatoriaus komponentas

 

Administratoriaus ir naudotojo komponentas
 
 

Bendrojo naudojimo elementas

 

);
}
```

Tipų lankstumas

Laikas paskutiniams dideliems pokyčiams. Dabartinės versijos komponentas palaiko tik tokius vaidmenis eilutė. Galime turėti kelis skirtingus
turto tipai, kuriuos norėtume patikrinti. Skaičiai arba pasirinktiniai tipai nėra nieko ypatingo. Aš pridėsiu bendrinių tipų palaikymą.

Pirmasis žingsnis - pokyčiai IGuardService sąsaja. Įgyvendinimas priklausys nuo testuojamos vertės tipo. Tai gali būti
būti bet kas, todėl sąsaja turėtų būti tvarkoma.

 eksporto sąsaja IGuardService {
     checkRole: (roles: ROLE[]) => boolean;
 }

Dabar jis užima masyvą ROLE bendrinis tipas. Mūsų paprastas įgyvendinimas šiek tiek pasikeis.

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

Mums reikia pridėti tipo parametrą, tačiau galime parengti realizaciją, kuri palaiko IRole sąsaja.

sąsaja IRole {
name: string;
}

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

Antrasis žingsnis - perkelti šį pakeitimą į IGuardProps.

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

Ir atitinkamai į Apsauga komponentas.

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

Ir mūsų naudojimo atvejai

export const AppHeader: FC = () =&gt; {
     const guardService = new SimpleGuard();
     const roleService = new RoleGuardService();
     return (
         <header>
             <nav>
                 <ul>
                     <Guard<IRole&gt; requiredRoles={[{{pavadinimas: "ADMIN"}]} guardService={roleService}&gt;
                         <li>Tik administratoriaus komponentas</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={{["USER"]} guardService={guardService}&gt;
                         <li>Tik naudotojo komponentas</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={{["MODERATOR"]} guardService={guardService}
                                    draudžiama={() =&gt; <div>Draudžiama - tai gali matyti tik moderatorius</div>}>
                         <li>Moderatoriaus komponentas</li>
                     </Guard>
                     <Guard<string&gt; requiredRoles={{["USER", "ADMIN"]} guardService={guardService}&gt;
                         <li>Administratoriaus ir naudotojo komponentas</li>
                     </Guard>
                     <li>Bendrojo naudojimo elementas</li>
                 </ul>
             </nav>
         </header>
     );
 }

Šiame pavyzdyje aš naudoju abi įgyvendinimo IGuardservice tik iliustraciniais tikslais. Tikrais naudojimo atvejais
tikriausiai naudosite tik vieną.

Specializuoti komponentai ir dėliojimas

Svetainė Apsauga gali būti įterptas. Tik nepamirškite, kad prieiga bus sprendžiama eilės tvarka nuo daugumos išorinių instancijų.

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>Tik administratoriaus komponentas</li>
                         </Guard>
                         <Guard<string&gt; requiredRoles={{["USER"]} guardService={guardService}&gt;
                             <li>Tik naudotojo komponentas</li>
                         </Guard>
                         <li>Administratoriaus ir naudotojo komponentas</li>
                         <Guard<string&gt; requiredRoles={{["MODERATOR"]} guardService={guardService}
                                        draudžiama={() =&gt; <div>Draudžiama - tai gali matyti tik moderatorius</div>}>
                             <li>Moderatoriaus komponentas</li>
                         </Guard>
                     </Guard>
                     <li>Bendrojo naudojimo elementas</li>
                 </ul>
             </nav>
         </header>
     );
 }

Pirmiau pateiktame pavyzdyje Moderatoriaus komponentas niekada negalėjo pasirodyti, nes naudotojas gali atlikti tik vieną vaidmenį. Pirmasis Apsauga ribos
vaidmenis į ADMIN ir VARTOTOJAS, todėl MODERATORIUS niekada nepraeis pirmojo patikrinimo.

Galime kurti specializuotus komponentus, kurie paslepia kai kurias savybes.

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

}

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

Tik administratoriaus komponentas
 


Tik naudotojo komponentas


Draudžiama - tai gali matyti tik moderatorius
}>

Moderatoriaus komponentas



Administratoriaus ir naudotojo komponentas

 

Bendrojo naudojimo elementas

);
}
```

Šiuo atveju "AdminGuard" iš anksto apibrėžti ADMIN vaidmuo. Dėl pasekmių turime aiškiai apibrėžti tipą ROLE tipas
parametras.

Apibendrinimas

Šiame straipsnyje parodysiu, kaip sukurti ir naudoti Apsauga React komponentas. Pradedame nuo sudėtingo kodo, kurį sunku
skaityti ir prižiūrėti. Mes vystome jį į daugiau kūrėjas draugišką būseną ir įdiegti pasirinktinį funkcinį komponentą. Toliau mes
išplėsti komponentą, pridedant papildomų funkcijų, pertvarkyti ištraukimo paslaugą ir galiausiai pridėti generinių tipų.

Galiausiai turime komponentą, kurį galima įterpti į lizdą, yra lengva testuoti ir prižiūrėti.

Susiję straipsniai

Programinės įrangos kūrimas

React privalumai ir trūkumai

Kodėl verta naudoti React? Kokių privalumų turi ši JavaScript biblioteka? Norėdami sužinoti atsakymus, pasinerkite į šį straipsnį ir sužinokite tikruosius React naudojimo privalumus.

The Codest
Cezary Goralski Software Engineer

Prenumeruokite mūsų žinių bazę ir būkite nuolat informuoti apie IT sektoriaus patirtį.

    Apie mus

    The Codest - tarptautinė programinės įrangos kūrimo bendrovė, turinti technologijų centrus Lenkijoje.

    Jungtinė Karalystė - būstinė

    • 303B biuras, 182-184 High Street North E6 2JA
      Londonas, Anglija

    Lenkija - vietiniai technologijų centrai

    • Fabryczna biurų parkas, Aleja
      Pokoju 18, 31-564 Krokuva
    • Brain Embassy, Konstruktorska
      11, 02-673 Varšuva, Lenkija

      The Codest

    • Pagrindinis
    • Apie mus
    • Paslaugos
    • Case Studies
    • Sužinokite, kaip
    • Karjera
    • Žodynas

      Paslaugos

    • Patariamoji tarnyba
    • Programinės įrangos kūrimas
    • Galinės dalies kūrimas
    • Priekinės dalies kūrimas
    • Staff Augmentation
    • Atgalinės versijos kūrėjai
    • Debesų inžinieriai
    • Duomenų inžinieriai
    • Kita
    • QA inžinieriai

      Ištekliai

    • Faktai ir mitai apie bendradarbiavimą su išoriniu programinės įrangos kūrimo partneriu
    • Iš JAV į Europą: Kodėl Amerikos startuoliai nusprendžia persikelti į Europą?
    • Technikos plėtros centrų užsienyje palyginimas: Tech Offshore Europa (Lenkija), ASEAN (Filipinai), Eurazija (Turkija)
    • Kokie yra svarbiausi CTO ir CIO iššūkiai?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Website terms of use

    Autorinės teisės © 2026 The Codest. Visos teisės saugomos.

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