i have a module named PermissionChecker. Code below
const PermissionChecker = ({children, permissions, needs, all}) => {
let hasAccess = false;
if (typeof needs !== "function") {
const needsToArray = Array.isArray(needs) ? needs : [needs];
const checker = el => permissions.includes(el);
hasAccess = all ? needsToArray.every(checker) : needsToArray.some(checker);
} else {
hasAccess = needs(permissions);
}
return hasAccess ? {children} : null;
};
export default connect(
({appState}) => ({permissions: appState.get('userPermissions')}), null)(PermissionChecker);
And this is the usage case for PermissionChecker...
<Category icon="icon-user" label="User Management">
<PermissionChecker needs={(perms) => { ... }} all>
<Link icon="icon-plus" to="users/create">Create User</Link>
<Link icon="icon-cross" to="users/delete">Delete User</Link>
</PermissionChecker>
</Category>
<Category icon="icon-something" label="Another category">
<Link icon="icon-plus" to="something/create">Create a something</Link>
<Link icon="icon-cross" to="something/delete">Delete a something</Link>
</Category>
My question is ...
i know with fiber it is possible to return multiple react elements.
With this hierarchy, in Category's render method what will be props.children? PermissionChecker or Link?
I want to bypass PermissionChecker if it returns children. Is it possible with fiber?
props.children is always the children you pass with JSX. It doesn’t depend on what the components actually return. So I don’t think Fiber would change this in any way.
I’m not sure I understand what you mean by “bypass” in this case. Maybe you could create a complete runnable code snippet that illustrates your problem? It is not clear.
Hi @gaearon. Thanks for response.
Currently my components are complicated. I can create a simple code snippet to tell my trouble.
But for now i can say this. I'm passing parent method to children to lifting up state. When PermissionChecker component goes around Category and Link component i can't do that. I'm using React.Children.map in Category render and while iterating children i use React.CloneElement to pass props to children.
If my description is not clear still, i will create a snippet code.
Generally I don't recommend relying on cloneElement a lot. It's usually a sign you should restructure your components around data rather than try to manipulate the elements.
Yes, a simplified example would help.
Hi @gaearon. I have just create a repo for this. I add screenshot also, if you want to quick look. Now it is working but when i add PermissionChecker around components it breaks.. Any advice to prevent cloneElement? I don't have any idea :/
Thanks very much.
I recommend you to stop using cloneElement() for “wiring up” the component hierarchy.
Instead, you can describe your hierarchy as a data structure like this:
var links = [{
type: 'link',
to: '#',
text: 'Link 1',
}, {
type: 'category',
links: [{
type: 'link',
to: '#',
'Link 2'
}]
// etc
}]
Then you can render <Navigation structure={links} />, and have that component recursively read the data structure and build <Category> and <Link> elements out of it with explicit isActive and onToggle props right away.
The problem with how you use cloneElement is it kinda breaks React paradigm: the moment you extract a block of <Link>s into a <MyLinkSection> component, it stops working. So this demonstrates cloning children recursively is not a good approach.
There is another alternative solution, which is to use “context”, but it’s an experimental feature with many pitfalls and will change in the future, so I don’t recommend it unless you’re very experienced with React. Context, however, is how React Router solves this problem.
I hope this helps!
I’m closing since this is more of a usage question rather than an issue.
Most helpful comment
Generally I don't recommend relying on cloneElement a lot. It's usually a sign you should restructure your components around data rather than try to manipulate the elements.
Yes, a simplified example would help.