I need to render a component based on the user role.
For example: If the user is a sales persons he would see both buttons. But if he is support he would see only the second button.
import React from 'react';
import Button from './MyCustomButton';
class App extends React.PureComponent {
render() {
return (
<Grid>
<Button> // visible only for sales manager
Action A
</Button>
<Button> // visible for support and sales manager
Action B
</Button>
</Grid>
)
}
}
I would really like to avoid if-else statements inside the render. Keep it clean as possible.
Is there a good design or some tools/decorator that could be useful here?
I've already handled it in the server side but I need a clean solution for the client side as well.
thanks.
You can inline ternary statements directly into your component tree, as shown below. If these boolean expression would evaluate to false
, react will skip them automatically.
class App extends React.PureComponent {
render() {
const user = this.props.user;
return (
<Grid>
{user.isSalesManager && <Button>
Action A
</Button>}
{(user.isSalesManager || user.isSupport) && <Button>
Action B
</Button>}
</Grid>
)
}
}
In order to do that, you need to have the information about the user role in the props though.
Read more on conditional rendering in the React documentation.
One way you could do this is with an Authorizor component. It would be a very simple function that does your validation for you like normal, and just checks an authLevel. If you need to adjust this to work with your auth model thats fine.
function Authorizor(props) {
if (props.authLevel > props.user.authLevel) {
return null;
}
const { ComponentToValidate } = props;
return <ComponentToValidate {...props} />;
}
then usage would be something like
<Authorizor authLevel={1} ComponentToValidate={Button} {...this.props} />
in your example this would look like.
class App extends React.PureComponent {
render() {
return (
<Grid>
<Authorizor authLevel={2} ComponentToValidate={Button} label="Action A" onClick={this.handleActionAThingy} {...this.props} />
<Authorizor authLevel={1} ComponentToValidate={Button} label="Action B" onClick={this.handleActionBThingy} {...this.props} />
</Grid>
)
}
}
If it's just a matter of 'cleaner' look and not lack of condition (because you will have to have it somewhere) you could create simple reusable component:
const Visibility = ({ isVisible, children }) => (
isVisible ? React.Children.only(children) : null;
)
and use it like that
<Grid>
<Visibility isVisible={user.isSalesManager}>
<Button> // visible only for sales manager
Action A
</Button>
</Visibility>
<Visibility isVisible={user.isSalesManager || user.isSupport}>
<Button> // visible for support and sales manager
Action B
</Button>
</Visibility>
</Grid>
it's hard to come up with much better solution without knowing more about your application architecture, but if you keep your user roles in some kind of store accessible from anywhere (redux, context, whatever) you could create very similar component that accepts roles needed to see it's children (let's say an array of strings) and possibly some kind of descriptor (like all
, oneOf
etc. if your permissions system is more complicated) and component itself grabs needed data from global store and compares it to props it got. If that's your use case i can provide example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With