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

Я хотел бы поделиться шаблоном дизайна, который я использую, чтобы управлять тем, что пользователи могут или не могут видеть в приложениях React, которые я создаю.

Это может оказаться полезным, если вашему приложению необходимо управлять тем, что пользователи могут видеть, на основе некоторых настроек в их учетной записи.

В примере, который я собираюсь показать, несколько разных компонентов работают вместе:

  1. React для библиотеки компонентов пользовательского интерфейса
  2. TypeScript для обеспечения безопасности типов
  3. Redux для глобального управления состоянием
  4. 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>
  )
}

Ответить