background

In 2202 years, front-end engineers have started to roll up. After learning VUe2 and VUe3 recently, they still want to roll up a little more, so they continue to learn React and try to build a general template framework for background management. This involves fine-grained button permission design, which leads to the following.

Traditional permission verification

In VUE, for button level permission verification, it is possible to simply encapsulate a V-permission instruction to achieve button permission control. However, in React, there seems to be no instruction and only one concept, so the instruction is not feasible. React permissions are checked in JSX:

{hasAuth ? (<button>Permissions button</button>) : null}
Copy the code

This is pretty straightforward, but if you have to write a long list of things for each button, it’s a lot of work, and it seems redundant. So the higher-order components are derived.

Higher-order component-based permission verification

Use higher-order components to wrap the original component for permission verification purposes:

// AuthBtn
import React from 'react';
import { Button } from 'antd';

export interfaceAuthBtnProps { auth? :string
}

const AuthBtn: React.FC<AuthBtnProps> = (props) = > {
  let { auth, children } = props;
  // btnIds should have a back end interface that tells the front end user what button permissions are available
  let btnIds = ['read'.'edit'];
  let hasAuth = btnIds.includes(auth);
  // This can be packaged according to actual requirements
  return <>{hasAuth ? (<Button>{children}</Button>) : null}</>
};
export default AuthBtn;
Copy the code

This can achieve Button permissions, but a new problem arises, this is only for the Button component encapsulation, if other presentation components. Each component has a wrapper that encapsulates multiple components separately. Far from what we expected, can we implement logic once and apply to all components?

High – order component permission verification based on polymorphism

Based on the previous question, we can pass the components we want to render directly through props, so we have the following implementation:

import React from 'react'

export interface AuthProps<E> {
  as? : E fallback? : React.ReactNode auth? :string | boolean | (() = > boolean), children? : React.ReactNode }const Auth = <E extends React.ElementType>(props: AuthProps<E>) => { const { as, fallback, auth, ... rest } = props const Component = as ?? 'span' let hasAuth = false if (auth === undefined) { return<Component {. rest} / >} else if (typeof auth === 'function') { hasAuth = auth() } else if (typeof auth === 'boolean') { hasAuth = auth } else {// todo custom permission logic verification hasAuth = ["]. Includes (auth)} if (hasAuth) {return<Component {. rest} / >
  }
  return <>{fallback ? fallback : null}</>
}

export default Auth

Copy the code

The component to be rendered is passed as an AS parameter to achieve the desired functionality

But since we use typescript, we want to be able to write components on the side with specific attribute cues based on the values we pass in as

Before modification:

After transforming:

The implementation code is posted directly below:

import React from 'react'

type AuthComponentProps<E extends React.ElementType> = {
  as? : E fallback? : React.ReactNode auth? :string | (() = > boolean) | boolean
}

type AuthProps<E extends React.ElementType> = AuthComponentProps<E> &
  Omit<React.ComponentProps<E>, keyof AuthComponentProps<E>>

const Auth = <E extends React.ElementType>(props: AuthProps<E>) => { const { as, fallback, auth, ... rest } = props const Component = as ?? 'span' let hasAuth = false if (auth === undefined) { return<Component {. rest} / >} else if (typeof auth === 'function') { hasAuth = auth() } else if (typeof auth === 'boolean') { hasAuth = auth } else {// todo custom permission logic verification hasAuth = ["]. Includes (auth)} if (hasAuth) {return<Component {. rest} / >
  }
  return <>{fallback ? fallback : null}</>
}

export default Auth

Copy the code

The implementation of the hint function is mainly the definition of the TS type, which is somewhat obscure in detail.

Two learning materials are recommended:

A, www.bilibili.com/video/BV1cS…

Second, the github.com/kripod/reac…

The above are the videos and projects I watched when I was studying, and I think the benefits are great. The following is the frame I built while learning (Xiao Sheng BB.jpg).

Third, github.com/HULANG-BTB/…