Join the conversation

Sign in to join this conversation, and others like it, in the communities you care about.

React

A community of developers, designers and others who love React.js. ⚛️

React / General

Apply custom props (Compound Components)

Apply custom props (Compound Components)

React/General · September 9, 2018 at 7:45pm

Apply custom props (Compound Components)

React / General · September 9, 2018 at 7:45pm (Edited 5 months ago)
Hello :)
edit: (maybe someone has the same question)
The answer to this are compount components. Actually there are two ways to achieve this result. By iterating over all child components and adding props just to the components you want to. Or you can use the new React context API. Either way the user is fully in charge of the UI and the User does not have to apply any props them self (like it is with render props).
Original Post:
I have a question about applying props on react elements where I do not know the exact children before. E.g. in a list, table, or a form where I eventually get the data from a server and render them with children.map() or something similar. Right know I am working on applying props on form inputs.
So my question is if there is a possibility to add props to certain types of elements when using:
class Form extends React.Component { constructor(props){...} render() { <form>{children}</form> } }
Now the children within this form are maybe nested like
<div> <input type="email" ... /> </div> <div> <div>Some text</div> <CustomComponet> <input type="text" ... /> </CustomComponent> </div>
And now i would like to apply custom components to all input elements, like onClick handlers etc, so that the Form component does the state management and all the stuff so I do not have to handle every form in every container.
I came up with an idea I red on a gist: https://gist.github.com/Vinorcola/f3d59ae780c0becc1644.
This basically renders a function within the Form components render function and recursively renders the react components, where I have the opportunity to add custom props.
const processChildren = (generateMergeProps, element) => { return React.Children.map(element.props.children, (child) => { if (!child.props) { return child; } if (React.Children.count(child.props.children) === 0) { return React.cloneElement(child, generateMergeProps(child)); } return React.cloneElement( child, generateMergeProps(child), processChildren(generateMergeProps, child), ); }); };
and in the mergeProps I add the props on to the elements I want...
generateMergeProps(element) { let props = {}; if(element.props.type === 'email') { props = { ...element.props, someOtherProp: 'someValue', someFunc: () => {...} } } return props; }
and the render function would look like:
render() { return ( <div>{processChildren(this.generateMergeProps, this)}</div> ) }
however I wondered if this is even a good idea or if there is some other way to achieve this?






September 9, 2018 at 7:47pm

Without reading too much into your question - have you taken a look at higher order components or render props?

like-fill
1
  • reply
  • like

Hey :) thanks for responding... I did, but for what I understand HOCs using needs to know the exact component they are rendering. And for renderProps that would be the same.

But imagine you want to build a form that is declarative:

<form>
    <input type="text" ... />
    .
    .
    .
</form>

If you only render inputs within this form you could use a HOC or render prop and predefine your data structure. But if the user needs more than inputs in their forms e.g. divs, fieldsets.

<form>
    <div>Email</div>
    <div>
        <input type="email" ... />
    </div>
</form>

  • reply
  • like

and you just want to write a plain <html> form and apply only props to inputs how could you do that

and i want to create a plain html form and inject the props invisible for the user.

otherwise I could do something like:

const (props) => {
    return (form) => (
        <input type="email" onChange={form.onChange}
    )
}; 

But that is not really satisfying

  • reply
  • like

At glance, you might love recompose’s mapProps

like-fill
1
  • reply
  • like

Thx, I will take a look at it :)

  • reply
  • like

This looks very interesting, thank you phillip

  • reply
  • like

September 10, 2018 at 6:38am

Look for Compound Components I think it's your case :)

like-fill
1
  • reply
  • like

September 10, 2018 at 9:00pm

Thank you I will take a look at... Its great to find so many people who help out :)

  • reply
  • like

September 10, 2018 at 10:02pm

Look for Compound Components I think it's your case :)

Compound Components are exactly what I wanted to see... do you know if there is any trade off (performance) using this over lets say render props (I do not not the performance here, but the trade off that the user is able to render whatever they like, but they have to apply the props them selfs)

  • reply
  • like

I found an interesting article about it using the react context api... https://blog.logrocket.com/guide-to-react-compound-components-9c4b3eb482e9 I think I have found what I need :) thanks to all of you...

  • reply
  • like

September 12, 2018 at 9:36am

Just in time, I believe that [react-native-formik](https://github.com/bamlab/react-native-formik) does exactly this.

  • reply
  • like

Log in or sign up to chat