Home > Blockchain >  How to write a Typescript React Component Wrapper
How to write a Typescript React Component Wrapper

Time:05-17

A custom ReactJS wrapper component should be used to wrap code and only render it, if the user has the required permission. Therefore, it needs to accept two parameters, the children that shall be rendered as well as the permission it needs to check for.

The idea is to use it like this:

const AdminTools = () => {
  return (
    <RequirePermission require_permission="ui:see_admin_menu">
      <>
        <h1>Sudo mode</h1>
        <Link href="/intern/users/">
          <a>
            <ActionCard link>User management</ActionCard>
          </a>
        </Link>
      </>
    </RequirePermission>
  );

};

What I came up with so far is the following code:

const RequirePermission = (children: React.FC<{}>, required_permission: string) => {
    const user = useContext(AuthContext);

    let hasPermission = false;
    if (user.state == AuthState.Authorized) {

        user.user?.realm_access?.roles.forEach(role => {
            if (permissions[role].includes(required_permission)) {
                hasPermission = true;
            }
        });
    }

    if (hasPermission) {
        return children;
    } else {
        return <div />;
    }

};

export default RequirePermission;

When using the code snippet as described above, the following error is thrown:

    Type '{ children: Element; require_permission: string; }' is not assignable to type 'IntrinsicAttributes & FC<{}>'.
  Property 'children' does not exist on type 'IntrinsicAttributes & FC<{}>'.ts(2322)
'RequirePermission' cannot be used as a JSX component.
  Its return type 'FC<{}> | Element' is not a valid JSX element.
    Type 'FunctionComponent<{}>' is missing the following properties from type 'Element': type, props, keyts(2786)

I don't really understand the error message to be frank. Any help would be much appreciated.

//Edit:

Error messages given by proposed code:

This JSX tag's 'children' prop expects a single child of type 'ReactChildren', but multiple children were provided.ts(2746)

and

'RequirePermission' cannot be used as a JSX component.
  Its return type 'Element | ReactChildren' is not a valid JSX element.
    Type 'ReactChildren' is missing the following properties from type 'Element': type, props, key

CodePudding user response:

Try this, importing ReactChildren from react.

I wish i could explain this better, but i know typescript is expecting a JSX/TSX element, so we could use ReactElement for the return type.

For a better explanation on the children type

https://stackoverflow.com/a/58123882/7174241

import React, { ReactChildren, ReactElement, ReactNode } from "react";

interface RequireType {
  children: ReactChildren | ReactNode | ReactElement;
  required_permission: string;
}

const RequirePermission = ({ children, required_permission }: RequireType):ReactElement => {
  const user = useContext(AuthContext);

  let hasPermission = false;
  if (user.state == AuthState.Authorized) {
    user.user?.realm_access?.roles.forEach((role) => {
      if (permissions[role].includes(required_permission)) {
        hasPermission = true;
      }
    });
  }

 return <>{hasPermission ? children : null}</>

};

export default RequirePermission;
  • Related