Создание многоразового разрешения в React

Я хотел бы поделиться шаблоном дизайна, который я использую, чтобы управлять тем, что пользователи могут или не могут видеть в приложениях React, которые я создаю.
Это может оказаться полезным, если вашему приложению необходимо управлять тем, что пользователи могут видеть, на основе некоторых настроек в их учетной записи.
В примере, который я собираюсь показать, несколько разных компонентов работают вместе:
- React для библиотеки компонентов пользовательского интерфейса
- TypeScript для обеспечения безопасности типов
- Redux для глобального управления состоянием
- Bitmask для разрешений пользователей
Для начала предположим, что у вас есть простой компонент с некоторым текстом, который вы хотите показать или скрыть в зависимости от разрешения пользователя:
import React from "react"
const MyPage = () => {
return (
<div>
<div>
<p>Admin text</p>
</div>
<div>
<p>Manager text</p>
</div>
<div>
<p>Designer text</p>
</div>
</div>
)
}
Простой способ сделать это – проверить уровень разрешений пользователей в каждом конкретном случае.
Примечание: в приведенных ниже примерах я использую побитовый оператор and (&), чтобы проверить свое разрешение. Операция выдаст либо 1, либо 0. Замените свою собственную проверку, если ваша модель разрешение отличается.
import React from "react"
import { useSelector } from "react-redux"
enum Permission {
PERMISSION_NONE = 0x0,
PERMISSION_ADMIN = 0x1,
PERMISSION_MANAGER = 0x2,
PERMISSION_DESIGNER = 0x4,
}
interface IRootState {
account: {
status: Permission
}
}
const MyPage = () => {
const status = useSelector((state: IRootState) => state.account.status)
return (
<div>
{Permission.PERMISSION_ADMIN & status && (
<div>
<p>Admin text</p>
</div>
)}
{Permission.PERMISSION_MANAGER & status && (
<div>
<p>Manager text</p>
</div>
)}
{Permission.PERMISSION_DESIGNER & status && (
<div>
<p>Designer text</p>
</div>
)}
</div>
)
}
Этот пример работает, но по мере роста необходимости постоянного получения статуса пользователя. Это может стать проблемой.
Чтобы решить эту проблему, я создал компонент более высокого порядка, который обертывает каждый блок конфиденциальной информации и требует один аргумент для разрешения проверки. Компонент обрабатывает проверку статуса и логику отображения / скрытия.
Примечание. Этот пример лучше всего работает, если вы используете в своем приложении какой-либо поставщик глобального состояния.
interface IProps {
permission: Permission
}
const PermissionWrapper: React.FC<IProps> = ({ permission, children }) => {
const status = useSelector((state: IRootState) => state.account.status)
if (permission & status) {
return <>{children}</>
}
return null
}
Теперь я могу заключить в этот компонент любую конфиденциальную информацию и предоставить соответствующее разрешение для проверки.
const MyPage = () => {
return (
<div>
<PermissionWrapper permission={Permission.PERMISSION_ADMIN}>
<div>
<p>Admin text</p>
</div>
</PermissionWrapper>
<PermissionWrapper permission={Permission.PERMISSION_MANAGER}>
<div>
<p>Manager text</p>
</div>
</PermissionWrapper>
<PermissionWrapper permission={Permission.PERMISSION_DESIGNER}>
<div>
<p>Designer text</p>
</div>
</PermissionWrapper>
</div>
)
}