0

I am writing a custom functional component called Can which takes two arguments (an action identifier and a callback function to be used if access is denied) that can wrap other components and essentially checks if a user has access.

The component is as follows (the console.log statements are there for debugging and become important later):

const Can = (props) => {
  console.log("Can Component is executed");

  const roles = useSelector((state) => state.common.user.roles);

  roles.forEach((element) => {
    if (check(rules, element, props.perform, props.data)) {
      console.log(
        "Check matched for Role" + element + " - it can do " + props.perform
      );
      return <>{props.children}</>;
    }
  });

  console.log(
    "No match found for the current user to perform " + props.perform
  );
  return props.no();
};

The user has multiple roles (stored in the application wide state) and for each of these roles access is checked. Once a role grants access, it is supposed to return the children prop, otherwise it will return the no prop being the mentioned callback.

It is called as follows:

<Can perform={"ui:see_admin"} no={() => <h2>NoAccess</h2>}>
  <br />
  <b>Administration</b>
  <NavLink to="/admin/user">
    <UserAction>
      Benutzerverwaltung
      <span style={{ float: "right" }}>Coming soon</span>
    </UserAction>
  </NavLink>
</Can>

The problem I have is that even if the check function matches, the no() action is returned. The output in the console is:

  • Can Component is executed
  • Check matched for Role xxx - it can do yyy
  • No match found for the current user to perform xxx

And then props.no() is returned. Why does this happen?

Daniel
  • 1,398
  • 4
  • 20
  • 47
  • Functional programming involves the use of functions with don't have side effects. Your state hook causes side effects. This is a [**function** component](https://reactjs.org/docs/components-and-props.html#function-and-class-components). – Quentin Nov 18 '20 at 14:13
  • There are quite a few issues: what does the `check()` function do? It seems to expect an argument (`props.data`) which you do not pass to the `Can` component. Furthermore your component always return `props.no()`. Also, if you want to return a set of `<>props.children>` you need to specify a `key` props for each fragment. – secan Nov 18 '20 at 14:15

0 Answers0