React의 장단점
React를 사용해야 하는 이유는 무엇인가요? JavaScript 라이브러리의 장점은 무엇일까요? 이 글을 자세히 살펴보고 React 사용의 실제 이점에 대해 알아보세요.
조건부 렌더링 및 가드 컴포넌트를 사용하여 React에서 컴포넌트 가시성을 간소화하고 개선하는 방법을 알아보세요.
오늘은 제어하는 방법에 대해 논의하고자 합니다. React의 구성 요소 가시성. 하지만 시작하기 전에 작은
면책 조항:
현재 제시된 솔루션은 '해커'(누구든)로부터 애플리케이션을 보호한다는 의미에서 그다지 안전하지 않습니다.
엔드포인트를 보호하고 애플리케이션 설계에 모범 사례를 사용해야 한다는 점을 기억하세요. 이 솔루션은
작업을 조금 더 쉽게 만들어 줍니다.
가장 일반적인 기능 중 하나는 특정 권한이 있는 사용자 그룹에 대해서만 컴포넌트를 표시하는 것입니다,
역할 또는 권한을 추가합니다. 일반적인 해결책은 일부 만약
에 코드를 클릭하고 조건을 수동으로 확인하고 요소를 표시할지 여부를 선택합니다.
다음을 살펴보겠습니다. SimpleAppHeader
탐색 요소를 거의 포함하지 않는 컴포넌트입니다.
<!-- wp:paragraph -->
<p><code>타입스크립트 JSX<br>
export const SimpleAppHeader: FC = () => {<br>
반환 (<br>
<header><br>
<nav><br>
<ul><br>
{<br>
currentUser.role === "ADMIN" &&<br>
<li>관리자 전용 컴포넌트</li><br>
}<br>
{<br>
currentUser.role === "USER" &&<br>
<li>사용자 전용 구성 요소</li><br>
}<br>
{<br>
(currentUser.role === "ADMIN" || currentUser.role === "USER") &&<br>
<li>관리자 및 사용자 전용 구성 요소</li><br>
}<br>
<li>일반 사용 요소</li><br>
</ul><br>
</nav><br>
</header><br>
)<br>
}<br>
</code></p>
<!-- /wp:paragraph -->
"나쁘지 않은" 것 같습니다. 아마도 검사를 함수로 캡슐화하여 복잡성을 줄일 수 있을 것입니다. currentUser
는 어떤 객체
그에는 역할
속성이지만, 제어 메커니즘의 대상으로 사용하고자 하는 모든 것이 될 수 있습니다.
이 코드에는 몇 가지 문제가 있습니다. 만약 프로젝트 가 성장하면 많은 곳에서 이 구조를 사용할 것입니다. 따라서 복사해야 합니다,
어떻게든, 조건. 이러한 코드는 향후 유지 관리 및 변경이 어렵습니다. 특히 다음 중 액세스 규칙이 변경되는 경우
시간 예: 변경이 필요한 경우 currentUser
를 다른 것으로 바꿔야 합니다. 테스트하기가 매우 어렵습니다. 많은 테스트를 작성해야 합니다.
상태가 괜찮은지 확인하기 위한 것입니다.
이제 이 코드를 조금 단순화할 차례입니다. 몇 가지 메서드를 추출하여 코드를 더 짧고 덜 복잡하게 만들 수 있습니다:
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 = () => {
반환 (
{
isAdmin(currentUser.role) &&
관리자 전용 컴포넌트
}
{
isUser(currentUser.role) &&
사용자 전용 컴포넌트
}
{
(isAdminOrUser(currentUser.role)) &&
관리자 및 사용자 전용 컴포넌트
}
일반 사용 요소
)
}
```
유망해 보입니다. 노이즈나 반복되는 줄이 줄어듭니다. 코드가 더 읽기 쉽고 유지 관리가 더 쉬워집니다. 하지만 다음을 살펴보세요.
함수 isAdminOrUser
. 여기에는 두 가지 역할만 있습니다. 세 번째 역할을 도입하려면 다른 함수 집합을 만들어야 합니다.
역할을 결합한 버전입니다. 다른 버전으로 이동합니다.
기능을 소개합니다. hasRole
를 대체할 것입니다. isX
함수.
const hasRole = (role: string, requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => role === s);
반환 found !== undefined;
}
export const FilteringAppHeader: FC = () => {
반환 (
{
hasRole(currentUser.role, ["ADMIN"]) &&
관리자 전용 컴포넌트
}
{
hasRole(currentUser.role, ["USER"]) &&
사용자 전용 컴포넌트
}
{
hasRole(currentUser.role, ["ADMIN", "USER"]) &&
관리자 및 사용자 전용 컴포넌트
}
일반 사용 요소
)
}
```
이제 괜찮아 보입니다. 여전히 코드의 HTML 부분에 조건이 있지만 이제 테스트할 수 있습니다. hasRole
기능 및 신뢰
가 올바른 매개변수 집합과 함께 사용됩니다. 이제 역할을 추가하거나 변경하기가 더 쉬워졌습니다. 모든 역할이 포함된 배열을 사용합니다.
필요한 역할을 수행합니다.
그러나 이 솔루션은 currentUser
객체입니다. 객체가 어떤 식으로든 전역적이거나 접근하기 쉽다고 가정합니다.
애플리케이션의 모든 위치에서 사용할 수 있습니다. 그래서 우리는 이것을 캡슐화하려고 할 수 있습니다. 물론 hasRole
함수입니다:
const hasRole = (requiredRole: string[]): boolean => {
let found: string | undefined = requiredRole.find(s => currentUser.role === s);
return found !== undefined;
}
그러나 그것은 우리에게 거의 아무것도 제공하지 않습니다.
Guard
구성 요소이제 전체 로직을 캡슐화하는 컴포넌트를 만들 차례입니다. 이름을 Guard
이렇게 사용하고 싶습니다.
export const GuardedAppHeader: FC = () => {
반환 (
);
}
컴포넌트에는 두 가지 속성이 필요합니다. 첫째 어린이
보호되는 콘텐츠에 대한 책임이 있습니다. 둘째 필수 역할
그
액세스 권한을 부여하는 역할 배열을 처리합니다.
이 구조의 표현이 필요합니다. 매우 간단합니다. 우리는 타입을 확장합니다. React.PropsWithChildren
그에는 어린이
속성을 추가합니다. 물론 해당 속성을 유형에 수동으로 추가하고 확장자를 생략할 수도 있습니다.
인터페이스 IGuardProps 확장 React.PropsWithChildren {
requiredRoles: 문자열[];
}
구성 요소 자체도 간단합니다. 우리는 재사용할 것입니다 hasRole
함수를 사용할 수 있습니다.
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 {
반환 ;
}
}
"`
여기서 멈추라고 말할 수도 있지만 너무 쉬울 것입니다. 이제 컴포넌트가 생겼고, 이를 극한까지 활용할 수 있습니다 😀.
첫 번째 단계는 수표의 외부화입니다. currentUser
는 하드코딩된 값입니다. 이 값을 캡슐화하고 싶습니다.
를 일부 서비스에 추가하면 역할을 확인하는 방법을 '알게' 됩니다. 기술적으로 이는 우리가 hasRole
함수를 다른
클래스.
간단한 인터페이스를 만듭니다. IGuardService
속성이 하나만 있는 경우 - hasRole
.
내보내기 인터페이스 IGuardService {
checkRole: (roles: string[]) => boolean;
}
이제 간단한 구현은 다음과 같습니다.
SimpleGuard 클래스는 IGuardService를 구현합니다 {
checkRole(roles: string[]): boolean {
let found: 문자열 | undefined = roles.find(e => e === currentUser.role);
return found !== undefined;
}
}
이를 사용하려면 다음을 변경해야 합니다. IGuardProperties
및 사용 사례.
내보내기 인터페이스 IGuardProps는 React.PropsWithChildren을 확장합니다.
requiredRoles: 문자열[];
guardService: IGuardService;
}
// ...
const AppHeader: FC = () => {
const guardService = 새로운 SimpleGuard();
반환 (
관리자 전용 컴포넌트
사용자 전용 컴포넌트
관리자 및 사용자 구성 요소
일반 사용 요소
);
}
```
이제 컴포넌트는 다음과 같습니다:
export const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) { {
반환 (
{props.children}
);
} else {
반환 ;
}
}
훨씬 나아졌습니다. GuardService
역할을 확인하는 로직으로부터 우리를 분리합니다. 우리는 우리의
컴포넌트입니다. 일반적인 사용 사례는 테스트에서는 모의 구현을 사용하고 프로덕션 코드에서는 일부 "실제" 구현을 사용하는 것입니다.
다음 개선 사항은 사용자 지정 처리입니다. 금지됨
요소를 렌더링합니다. 현재 솔루션은 빈 요소를 렌더링합니다. 먼저
변경 IGuardProps
해당 요소를 렌더링할 함수를 추가합니다.
내보내기 인터페이스 IGuardProps 확장 React.PropsWithChildren {
requiredRoles: 문자열[];
guardService: IGuardService;
forbidden?: () => React.ReactNode;
}
이 속성은 선택적 속성이며 이름은 물음표 문자로 끝납니다. 따라서 함수 또는 정의되지 않음
. 다음을 수행해야 합니다.
에서 처리합니다. Guard
컴포넌트입니다.
export const Guard = (props: IGuardProps) => {{
if (props.guardService.checkRole(props.requiredRoles)) { {
반환 (
{props.children}
);
} else if (props.forbidden === undefined) {
반환 ;
} else {
반환 (
{props.forbidden()}
);
}
}
// ...
export const AppHeader: FC = () => {
const guardService = 새로운 SimpleGuard();
반환 (
관리자 전용 컴포넌트
사용자 전용 컴포넌트
금지됨 - 관리자만 볼 수 있습니다.
}>
중재자 구성 요소
관리자 및 사용자 구성 요소
일반 사용 요소
);
}
```
마지막 큰 변화를 맞이할 시간입니다. 현재 버전 컴포넌트는 다음과 같은 역할만 지원합니다. 문자열
. 여러 가지 다른
확인하려는 속성 유형입니다. 숫자나 사용자 정의 유형은 특별한 것이 아닙니다. 제네릭 지원을 추가하겠습니다.
첫 번째 단계는 IGuardService
인터페이스가 필요합니다. 구현은 테스트된 값의 유형에 따라 달라집니다. 다음과 같습니다.
가 무엇이든 될 수 있으므로 인터페이스가 이를 처리해야 합니다.
export interface IGuardService {
checkRole: (roles: ROLE[]) => boolean;
}
이제 다음과 같은 배열이 필요합니다. 역할
일반 유형. 간단한 구현이 약간 변경됩니다.
SimpleGuard 클래스는 IGuardService를 구현합니다.
checkRole(roles: string[]): boolean {
let found: string | undefined = roles.find(e => e === currentUser.role);
return found !== undefined;
}
}
유형 매개 변수를 추가해야 하지만 다음을 지원하는 구현을 준비할 수 있습니다. IRole
인터페이스.
인터페이스 IRole {
이름: 문자열;
}
//...
RoleGuardService 클래스는 IGuardService를 구현합니다 {
checkRole(roles: IRole[]): boolean {
let find: IRole | undefined = roles.find(e => e === userWithRole.role);
return found !== undefined;
}
}
```
두 번째 단계는 이 변경 사항을 다음과 같이 전파하는 것입니다. IGuardProps
.
인터페이스 IGuardProps 확장 React.PropsWithChildren {
requiredRoles: ROLE[];
guardService: IGuardService;
forbidden?: () => React.ReactNode;
}
그리고 각각 Guard
컴포넌트입니다.
export const Guard = (props: IGuardProps) => {
if (props.guardService.checkRole(props.requiredRoles)) { {
반환 (
{props.children}
);
} else if (props.forbidden === undefined) {
반환 ;
} else {
반환 (
{props.forbidden()}
);
}
}
그리고 사용 사례
export const AppHeader: FC = () => {
const guardService = 새로운 SimpleGuard();
const roleService = new RoleGuardService();
반환 (
<header>
<nav>
<ul>
<Guard<IRole> requiredRoles={[{name: "ADMIN"}]} guardService={roleService}>
<li>관리자 전용 구성 요소</li>
</Guard>
<Guard<string> requiredRoles={["USER"]} guardService={guardService}>
<li>사용자 전용 구성 요소</li>
</Guard>
<Guard<string> requiredRoles={["MODERATOR"]} guardService={guardService}
forbidden={() => <div>금지됨 - 운영자만 볼 수 있습니다.</div>}>
<li>진행자 구성 요소</li>
</Guard>
<Guard<string> requiredRoles={["USER", "ADMIN"]} guardService={guardService}>
<li>관리자 및 사용자 구성 요소</li>
</Guard>
<li>일반 사용 요소</li>
</ul>
</nav>
</header>
);
}
이 예제에서는 두 가지 구현을 모두 사용합니다. IGuardservice
를 예로 들었습니다. 실제 사용 사례에서는
아마 하나만 사용할 것입니다.
그리고 Guard
를 중첩할 수 있습니다. 액세스 권한은 대부분의 외부 인스턴스 순서대로 해결된다는 점만 기억하세요.
export const NestAppHeader: FC = () => {
const guardService = 새로운 SimpleGuard();
반환 (
<header>
<nav>
<ul>
<Guard<string> requiredRoles={["USER", "ADMIN"]} guardService={guardService}>
<Guard<string> requiredRoles={["ADMIN"]} guardService={guardService}>
<li>관리자 전용 구성 요소</li>
</Guard>
<Guard<string> requiredRoles={["USER"]} guardService={guardService}>
<li>사용자 전용 구성 요소</li>
</Guard>
<li>관리자 및 사용자 구성 요소</li>
<Guard<string> requiredRoles={["MODERATOR"]} guardService={guardService}
forbidden={() => <div>금지됨 - 운영자만 볼 수 있습니다.</div>}>
<li>진행자 구성 요소</li>
</Guard>
</Guard>
<li>일반 사용 요소</li>
</ul>
</nav>
</header>
);
}
위의 예에서 진행자 구성 요소
는 사용자가 하나의 역할만 처리할 수 있기 때문에 표시되지 않을 수 있습니다. First Guard
제한
역할 ADMIN
그리고 USER
따라서 사회자
는 첫 번째 확인을 통과하지 못합니다.
일부 속성을 숨기는 특수 컴포넌트를 만들 수 있습니다.
export const AdminGuard = (props: Omit) => {
return
{props.children}
}
//...
export const SpecializedAppHeader: FC = () => {
const guardService = new SimpleGuard();
반환 (
관리자 전용 컴포넌트
사용자 전용 컴포넌트
금지됨 - 중재자만 볼 수 있음
}>
중재자 컴포넌트
관리자 및 사용자 컴포넌트
일반 사용 요소
);
}
```
이 경우 AdminGuard
미리 정의 ADMIN
역할을 정의해야 합니다. 결과적으로 다음과 같은 유형을 명시적으로 정의해야 합니다. 역할
유형
매개변수입니다.
이 문서에서는 다음을 만들고 사용하는 방법을 설명합니다. Guard
React의 구성 요소. 우리는 이해하기 어려운 복잡한 코드에서 시작합니다.
읽고 유지 관리합니다. 보다 개발자 친화적인 상태로 발전시키고 사용자 지정 기능 구성 요소를 도입합니다. 다음으로
추가 기능을 추가하는 컴포넌트 확장, 추출 서비스 리팩터링, 마지막으로 제네릭 유형을 추가합니다.
마지막으로 테스트 및 유지 관리가 쉬운 중첩 가능한 컴포넌트가 있습니다.