React: Component hierarchy in fiber?

Created on 29 Jan 2017  Â·  5Comments  Â·  Source: facebook/react

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?

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.

All 5 comments

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.

Repo: https://github.com/kafein/treemenu

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.

Was this page helpful?
0 / 5 - 0 ratings