Search code examples
javascriptreactjsstyled-components

Passing a styled component as a child to another component throws error


I am trying to create a generic layout component that can have other components passed to it. However, when I pass in other styled components, I receive the error, "Error: Objects are not valid as a React child (found: object with keys {$$typeof, render, attrs, componentStyle, displayName, foldedComponentIds, styledComponentId, target, withComponent, warnTooManyClasses, toString}). If you meant to render a collection of children, use an array instead."

This is my layout component

const LayoutOne = props => {
    const {
        backgroundColors,
        navbar: navbarChildren,
        sideNavLeft,
        sideNavRight,
        subGridChildren
    } = props;
    return (
        <Grid bg={backgroundColors}>
            <Navbar bg={backgroundColors}>{navbarChildren}</Navbar>
            <SideNav bg={backgroundColors}>{sideNavLeft}</SideNav>
            <Subgrid bg={backgroundColors}>
                {subGridChildren.map(child => (
                    <SubgridRow bg={backgroundColors}>{child}</SubgridRow>
                ))}
            </Subgrid>
            <SideNav bg={backgroundColors}>{sideNavRight}</SideNav>
        </Grid>
    );
};

This is how I am instantiating it:

<LayoutOne
    navbar={Navbar}
    subGridChildren={[Name, SocialIconContainer, Slider]}
    sideNavLeft={PreviousBackground}
    sideNavRight={NextBackground}
/>

I have tried passing a styled div with no styles:

const Navbar = styled.div``;

And also other components with styles.

const Name = styled.h1`
    color: #ffffff;
    font-family: "Monoton", cursive;
    z-index: 2;
    font-size: calc(1em + 6vw);
`;

Solution

  • When you use jsx to render and a component Babel substitute it with a call to createElement. React knows how to render elements, strings, numbers, but not how to render objects.

    In your case: const Navbar = styled.div``;, Navbar is a function, that in turns is an object. So you are not sending to React something that it knows how to render. If you want it to work you have to send it an element:

    <LayoutOne
        navbar={<Navbar >}
        ...
    />