Home > database >  How to get children of nested fonctionnal components
How to get children of nested fonctionnal components

Time:01-25

Is it possible to access grand children through React.children.map(), if children are components ?

For exemple, a component :

const MyComponent = () => {
    return (
        <div className={'demo'}>Demo</div>
    )
}

Used in another component :

const WhateverComponent = () => {
    return (
        <Layout>
            <MyComponent />
            <MyComponent />
            <MyComponent />
        </Layout>
    )
}

now the

layout :

const Layout = ({children}) => (

    const iterateOverChildren = (children) => {
        return React.Children.map(children, (child) => {
            if (!React.isValidElement(child)) {
                return child
            }

            if (child.props.className && child.props.className.includes('demo')) {

                // Never pass here...

                return React.cloneElement(child, {
                    ...child.props,
                    onClick: closePreview,
                    children: iterateOverChildren(child.props.children),
                })
            }

            return React.cloneElement(child, {
                ...child.props,
                children: iterateOverChildren(child.props.children),
            })
        })
    }    

    return (
        <div>
            {iterateOverChildren(children)}
        </div>
    )
)

Do I make a mistake or is this by design that it's not possible ?

If I do this before the className test it work :

child = typeof child.type === 'function' ? child.type(child.props) : child

... but typescript hardly warn me :

This expression is not callable.   
Not all constituents of type 'JSXElementConstructor<any>' are callable.     
Type 'new (props: any) => Component<any, any, any>' has no call signatures.

Any advice ?

CodePudding user response:

Yes, it is possible to access grandchildren through React.Children.map() if the children are components.

The React.Children.map() method allows you to iterate through an array of children elements, including grandchildren if they are passed down as components.

Here is an example of how you can use React.Children.map() to access grandchildren:

const Parent = (props) => {
return (
    <div>
      {React.Children.map(props.children, (child) => {
        return child;
      })}
    </div>
  );
};

const Child = (props) => {
  return (
    <div>
      <h1>Child Component</h1>
      {props.children}
    </div>
  );
};

const Grandchild = () => {
  return (
    <div>
      <h1>Grandchild Component</h1>
    </div>
  );
};

const App = () => {
  return (
    <Parent>
      <Child>
        <Grandchild />
      </Child>
    </Parent>
  );
};

n this example, the Parent component uses React.Children.map() to iterate through its children, which includes the Child component. The Child component then renders its own children, which in this case is the Grandchild component. In this way, you can access the Grandchild component through React.Children.map().

Please note that React.Children.map() method only iterates through children that are passed as props, if the children are in state it will not work, you will have to use a different method like recursion to access the grandchildren.

CodePudding user response:

Thanks for your reply,

My point is to make a generic layout in order to have a separate package. So I can't ask developers who will use it to pass children from props to props, and there may be no children

My problem is, in my example above, that I can't access MyComponent's "rendered HTML" (like a shadow DOM in a way) from the layout component, and I can't figure if there's a way..

Sorry if I'm not very clear

  • Related