简体   繁体   中英

How can I write React component that returns a class component as a functional component?

My Goal:

I'm currently implementing an AuthUserRole HOC component to handle the user roles: Manager and Employee. I'm using this tutorial to do so, but they use a functional component to return a class component.

My Question:

How can I write this HOC functional component to return a functional component instead of a class component? Or is there a better way?

Functional Component That Returns A Class Component:

// Imports: Dependencies
import React, { Component } from 'react';
import { connect } from 'react-redux';

// Component: Authorization
const AuthUserRole = (WrappedComponent, allowedRoles) => {
  class With AuthUserRole extends Component {
    render() {
      const userType  = this.props.userType;
      if (allowedRoles.includes(userType)) {
        return <WrappedComponent {...this.props} />;
      }
      else {
        return <h1>You are not allowed to view this page!</h1>;
      }
    }
  }

  const mapStateToProps = state => ({ user: state.login.userName, userType: state.login.userType });

  return connect(mapStateToProps)(AuthUserRole);
};

// Exports
export default AuthUserRole;

App.js (Where HOC Is Used):

<BrowserRouter history={history}>
  <Switch>
    {/* LANDING */}
    <Route path="/" component={Landing} exact />

    {/* APP */}
    <PrivateRoute path="/student/dashboard" component={Authorization(DashboardStudent,["Student"])}/>
    <PrivateRoute path="/admin/dashboard" component={Authorization(DashboardAdmin,["Admin"])}/>

    {/* LOGIN */}
    <Route path="/login" component={UserLogin}/>  

    {/* NOT FOUND */}
    <Route path="" component={NotFoundPage} />
  </Switch>
</BrowserRouter>

In order to return a function component, just return a function of props


const AuthUserRole = (WrappedComponent, allowedRoles) => {
   return (props) => {
...
   }
}

The recommended best practice is to use the useSelector hook instead of mapStateToProps and connect . So there are some other tweaks.

import React, { ComponentType } from 'react';
import { useSelector } from 'react-redux';

// Component: Authorization
const AuthUserRole = <Props extends {}>(WrappedComponent: ComponentType<Props>, allowedRoles: string[]) => {
  return (props: Props) => {
      // TODO: add your app's state type
      const userType = useSelector(state => state.login.userType);
      const user = useSelector(state => state.login.userName); // where is this used?

      if (allowedRoles.includes(userType)) {
        return <WrappedComponent {...props} />;
      }
      else {
        return <h1>You are not allowed to view this page!</h1>;
      }

  }
};

// Exports
export default AuthUserRole;

I added type annotations because you tagged this typescript , but I don't see any types in the current code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM