What are generic components, why use and make them

This is my term for components that can be passed nested components in their JSX and render those components. This allows setting up generic components that take other components as arguments and allows what each component does to be configured based on what children it is passed. The parent component can configure the children, set up the display, or just provide some diplay piece for the others to go inside.

Why is this Generic component setup useful

Because it allows component to be nested within one another, with enclosing components setting the stage for or configuring the components inside of them. This encourages and allows flexible component design. I use this general arrangement in all of my React component libraries, with examples in Geomap, Formbuilder, and Selectbox that I can think of offhand. I found that I could make much smaller, more multi-purpose components doing this. Together with using hooks Hooks howto p it gives me a couple ways to make it so I have flexible and reusable react code.

Nested components need to be rendered by the parent

The <Form> does not know about the nested <Selector> components in advance. To render them, the Form needs to put any passed children within its JSX. If the goal is to organize the child components, then Form needs to pass along arguments to them that will allow it to accomplish this.
Nesting some components -

return(  
  <Form>
    <Selector dataget={getDataYears} varname='year' />  
    <Selector dataget={getDataMonths} varname='month' />  
    <Selector dataget={getDataVars} varname='varname' />  
  </Form>  
)

In order to render Subcomponents use {props.children} -

Continuing the example, the return statement of <Form> would need to render the children by putting {props.children} in its JSX. The children could also be modified and then put in the JSX.

return(  
  <div>  
     <Buttons>
     {props.children}  
  </div>  
 )

Modifying props.children to pass props to the unknown children -

Passing props to known children is easy:

 return( <Comp {...props /> )

When the children are passed in the way I have been demonstrating however, the {props.children} need to be modified with the additional props.
Clone and modify the props.children to pass props.
I use this pattern for generic components that need to pass various arguments,props,hook value/setters to unknown children. Make sure to put the modified children in the JSX, and not the original
props.children.

  let pass = { // the values you want to pass }
  const propsToChildren = R.map(child => {  
    return React.cloneElement(child,   
     {...pass })  
  })(props.children)  
  // Pass the modified output, not the original props.children
  return(  
    <div>  
      {propsToChildren}  
    </div>  
  )

{props.children} allows access only to direct children

Consider this example where a nested component tree is passed to Component. Props.children of <Component> would have <Div> and <CustomList>. The more nested components <CompFn> and <p> are not present. Programatically created components are not accessible, so if the <CustomList> produces a <li>, that will not be in props.children either.

<Component>
  <Div>
    <CompFn>
      <p>
   ... 
  <CustomList/>
</Component>

If you need to pass props to nested children, pass at each level

Each component here (SelectBase, ViewBox) passes props to its children using the setup I showed with propsToChildren above. This way anything passed from Select to ViewBox also gets passed to the
Rect.

  <Select >
    <ViewBox viewBox={"0 0 800 450"}>
       <Rect />

I used this pattern to create generic structures
I use this pattern so that more general higher level elements accomplish functionality that will be used frequently separate from the children that implement more specific displays or actions.

Taking children and passing them to nested components -

The use case for this is to set up an involved structure and configure what it displays by passing different components. This way the overall strucuture is setup only once and then you just pass a different configuring each time. This is the same pattern I have been showing, but with a leapfrogging of where the {props.children} are put in the structure.

An example to show how this can work

// This component takes child to define the exact map
 <BaseMap { ...props } >
   <SpecializedMap />
 </BaseMap>

// But then passes that child to the full setup for the map, passes ...props  
// To the top level component because it passes props down.  
let const BaseMap = (props) => {
 return(
  <GeoMap {...props} >
    <SelectBase  >
      <ViewBox>
        {props.children}
      </ViewBox>
    </SelectBase>
  </GeoMap>
 )
}

The enclosing component will be able to access the children

The <ViewBox> has access to the <SpecializedMap /> via {props.children}. It works as if <ViewBox> <SpecializedMap/> </ViewBox> had been done. So ViewBox will access the map, and any props passed down through the whole structure can be given to the map via ViewBox.

I have encountered problems with this pattern

I did this in a case where the children were passed next to an element directly, and it triggered and error in React.
Example of the problem

      <ViewBox>
        <Rect>
        {props.children}
      </ViewBox>

I am not sure if it was my specific setup or a bug, but if using this pattern I avoid this right now since I have not been able to figure it out for sure.

That is the setup I use for configurable, nesting components

I suspect that there are other ways to accomplish this same task, but this is the pattern I have worked out for doing this so that I can make readily re-usable components where the exact display is determined by a structure of components, with each adding some part.