Add dynamic html attributes to child component from parent component - React.js
Asked Answered
H

2

6

Child Component:

export default class Button extends React.Component {
constructor(props) {
    super(props);
}
render() {
 return(
        <div className="form-group">
            <button

                // Need to add dynamic html attr here e.x: data-id

                key={index} 
                id={id} 
                className={`btn btn-default ${componentClass ? componentClass : null }`} 
                type="button"
                onClick={this.props.onClick}> 

                {text}

            </button>
        </div>
    );}}

Parent Component :

import Button from './Button';

Class App extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div className="s">
             <Button data-id="exampleData" />  // Need to add data-id attr to child button
            </div>
        );
    }

Button Component, have it's own default attributes like mentioned above : id,className,type,onClick

Parent Component, will call Button component and add some additional attributes like data-id,onChange.

note : after searched few ideas, I know that i can use spread operators like below :

Parent Component :

let dynamicAttributes = {"data-id":"someString", "data-attr":"someString", "data-url":"someString"};
    return (
        <div className="s">
         <Button dataSrc={ btnSrc } {...dynamicAttributes} />
        </div>
    );

I don't know how to call the dynamicAttributes in Button component as a html attrib

Expecting a good solution to this. Thanks in advance.

Used Destructing and Babel Showing error(unexpected token) like below image.

enter image description here

note: Already installed preset-env and preset-react.

Harbin answered 12/2, 2018 at 13:31 Comment(0)
B
4

You can make use of rest destructuring pattern in the child component. According to the documentation

Rest properties collect the remaining own enumerable property keys that are not already picked off by the destructuring pattern.

You should use rest destructing carefully when you are directly assigning the props to the DOM element, since from v16 onwards no check is done on the attributes and all properties are allowed to be passed on the DOM element, so even if it is not relevant, the properties will be passed on to the DOM element which you might not intend

P.S. Make sure that all properties that you don't want to pass on to the DOM are destructured separately.

Sample snippet

export default class Button extends React.Component {
  constructor(props) {
      super(props);
  }
  render() {
     const { onClick, dataSrc, ...rest } = this.props;
     return(
          <div className="form-group">
              <button
                  {...rest}
                  key={index} 
                  id={id} 
                  className={`btn btn-default ${componentClass ? componentClass : null }`} 
                  type="button"
                  onClick={onClick}> 

                  {text}

              </button>
          </div>
      );
  }
}
Bearden answered 12/2, 2018 at 13:42 Comment(9)
Already we have babel preset-env, but throws an error (unexpected token) in {...rest}, After install babeljs.io/docs/plugins/transform-object-rest-spread . Its working fine. Since we have preset-env, Then why we need additional plugin to support this feature.Harbin
@Balaji731, Check this issue, github.com/babel/babel-preset-env/issues/49. Here it is mentioned that all stage-x issues are not inclued in preset-env and rest-spread is a stage-3 proposal and hence you need a pluginBearden
so if i use babel-preset-stage-3, I do not need transform-object-rest-spread this right !!! With my understanding preset env supports only es6 completed features. Apart from that If I need to use other es6 less stable proposals ,I should install babel-stage-3 instead. Am I correct ?Harbin
Thanks @Shubham Khatri, need an other clarification If I need to use all es6 features. the following presets and plugins I have to install : babel-preset-stage-3, babel-preset-env and babel-polyfill. Apart from this, do i need anything to be installed ?Harbin
Well the above three works for me, not totally sure if for some other feature we need anything else or notBearden
Glad to have helpedBearden
Say we have a few more buttons in the child. In that case, I might have a different condition. Some styles are for one button, some are for others. So how to pass the values to a child from a parent in such case?Sibelle
@AkhilaHegde You can create multiple such object with your styles and pass them on to the respective button. Or you can have an object with the common set and the extra one you can pass on while spreading the common propertiesBearden
What's the syntax for setting the spread attributes? i.e. if I want to have in {...rest} attributes like onClick, style etc how would I do that? rest = {onClick=foo(), style={{style}}, ...}?Noyade
T
3

If you want to pass selective props, you can do:

<button 
  dataSrc={ btnSrc }
  data-id={this.props.data-id}
  data-attr={this.props.data-attr}
  data-url={this.props.data-url}
  key={index} 
  id={id} 
  className={`btn btn-default ${componentClass ? componentClass : null }`} 
  type="button"
  onClick={this.props.onClick}
> 
  {text}
</button>

And if you want to pass all the dynamic attributes, you should destructure the props accordingly. Something like this: {onClick, dataSrc, ...dynamicAttrs} = this.props; and then pass them like this:

<button 
  {...dynamicAttrs}
  dataSrc={ btnSrc }
  key={index} 
  id={id} 
  className={`btn btn-default ${componentClass ? componentClass : null }`} 
  type="button"
  onClick={this.props.onClick}
> 
  {text}
</button>

Also,visit this for reference: Transferring props

Tangled answered 12/2, 2018 at 13:53 Comment(1)
Already we have babel preset-env, but throws an error (unexpected token) in {...rest}, After install babeljs.io/docs/plugins/transform-object-rest-spread . Its working fine. Since we have preset-env, Then why we need additional plugin to support this featureHarbin

© 2022 - 2024 — McMap. All rights reserved.