根据用户角色隐藏一些React组件子项

我正在编写React和Redux中的单页应用程序(带有Node.js后端)。

我想实现基于角色的访问控制,并希望控制应用程序的某些部分(或子部分)的显示。

我将从Node.js获取权限列表,它只是一个具有这种结构的对象:

{
  users: 'read',
  models: 'write',
  ...
  dictionaries: 'none',
}

关键是保护资源,

是此资源的用户权限(以下之一: nonereadwrite )。

我正在将它存储到redux状态。 看起来很简单。

none权限将通过react-router路由onEnter/onChange钩子或者redux-auth-wrapper 。 这似乎也很容易。

但是,对任何组件视图应用read/write权限的最佳方式是什么(例如,如果用户具有{ models: 'read' }权限,则隐藏Models组件中的编辑按钮)。

我找到了这个解决方案,并为我的任务改变了一下:

class Check extends React.Component {
  static propTypes = {
    resource: React.PropTypes.string.isRequired,
    permission: React.PropTypes.oneOf(['read', 'write']),
    userPermissions: React.PropTypes.object,
  };

  // Checks that user permission for resource is the same or greater than required
  allowed() {
    const permissions = ['read', 'write'];
    const { permission, userPermissions } = this.props;
    const userPermission = userPermissions[resource] || 'none';

    return permissions.indexOf(userPermission) >= permissions.indexOf(permission)
  }

  render() {
    if (this.allowed()) return { this.props.children };
  }
}

export default connect(userPermissionsSelector)(Check)

其中userPermissionsSelector将如下所示: (store) => store.userPermisisons并返回用户权限对象。

然后用Check包装受保护的元素:

<Check resource="models" permission="write">
  <Button>Edit model</Button>
</Check>

所以如果用户没有modelswrite权限,该按钮将不会显示。

有没有人做过这样的事情? 有没有比这更“优雅”的解决方案?

谢谢!

PS当然,用户权限也会在服务器端进行检查。


好吧,我想我明白你想要什么。 我做了一些对我有用的事情,我喜欢我的方式,但我知道其他可行的解决方案都在那里。

我写的是HOC react-router风格。

基本上我有我的PermissionsProvider我初始化用户权限。 我有另一个使用Permissions HOC,它将我之前提供的权限注入到我的组件中。

因此,如果我需要检查特定组件中的权限,我可以轻松访问它们。

// PermissionsProvider.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import hoistStatics from "hoist-non-react-statics";

class PermissionsProvider extends React.Component {
  static propTypes = {
    permissions: PropTypes.array.isRequired,
  };

  static contextTypes = {
    permissions: PropTypes.array,
  };

  static childContextTypes = {
    permissions: PropTypes.array.isRequired,
  };

  getChildContext() {
    // maybe you want to transform the permissions somehow
    // maybe run them through some helpers. situational stuff
    // otherwise just return the object with the props.permissions
    // const permissions = doSomething(this.props.permissions);
    // maybe add some validation methods
    return { permissions: this.props.permissions };
  }

  render() {
    return React.Children.only(this.props.children);
  }
}

const withPermissions = Component => {
  const C = (props, context) => {
    const { wrappedComponentRef, ...remainingProps } = props;

    return (
      <Component permissions={context.permissions} {...remainingProps} ref={wrappedComponentRef} />
    );
  };

  C.displayName = `withPermissions(${Component.displayName || Component.name})`;
  C.WrappedComponent = Component;
  C.propTypes = {
    wrappedComponentRef: PropTypes.func
  };

  C.contextTypes = {
    permissions: PropTypes.array.isRequired
  };

  return hoistStatics(C, Component);
};

export { PermissionsProvider as default, withPermissions };

好吧,我知道这是很多代码。 但这些都是HOC(你可以在这里了解更多)。

高阶组件(HOC)是React中用于重用组件逻辑的高级技术。 HOC本身不是React API的一部分。 它们是从React的构图本质中浮现出来的一种模式。 具体而言,高阶组件是一个接收组件并返回新组件的函数。

基本上我这么做是因为我受到了路由器反应的启发。 每当你想知道一些路由的东西,你可以添加装饰@withRouter ,他们将道具注入你的组件。 那么为什么不做同样的事情呢?

  • 首先你必须设置提供者的权限
  • 然后在检查权限的组件上使用withPermissions装饰器

  • //App render
    return (
       <PermissionsProvider permissions={permissions}>
          <SomeStuff />
       </PermissionsProvider>
    );
    

    SomeStuff里面的某个地方有一个广泛分布的工具栏来检查权限吗?

    @withPermissions
    export default class Toolbar extends React.Component {
      render() {
        const { permissions } = this.props;
    
        return permissions.canDoStuff ? <RenderStuff /> : <HeCantDoStuff />; 
      }
    }
    

    如果你不能使用装饰器,就像这样导出工具栏

    export default withPermissions(Toolbar);
    

    这里是我在实践中展示的一个codesandbox:

    https://codesandbox.io/s/lxor8v3pkz

    笔记:

  • 我真的很简化权限,因为这个逻辑来自你的最终目的,为了演示的目的,我简化了它们。
  • 我认为权限是一个数组,所以这就是为什么我检查HOC中的PropTypes.array
  • 这是一个非常漫长而复杂的答案,我试图用我最好的能力来表达。 请不要在这里和那里烧我一些错误:)
  • 链接地址: http://www.djcxy.com/p/95353.html

    上一篇: Hide some React component children depending on user role

    下一篇: How to convert Unix time / time since the epoch to standard date and time?