Is there a way to pass props in a property [React]?

Hey guys,
I just want to know if there is a recommend way to pass props within a React porperty? For example, I’m having this property within my component:

<MyCustomElement onChange={this.saveValue.bind(this,'input-2')}/>

The problem is that binding here is an anti pattern. My next solution would be to use an arrow function, but this is an anti pattern too. So what would be the way to use only one saveValue function without writing a new one for each component?

In my case I’m using https://ant.design/components/select/ . Normally I would use e.target.id to identify the input, but the onChange method only passes the value, not the id or event object.

Why on earth would an arrow function be an “anti pattern”?

Just quote a SO answer:

Using arrow functions or binding in JSX is a bad practice that hurts performance, because each render will create a new function, which means that the garbage collector will have more work than needed.

Which means that the following code is an anti pattern:

<MyCustomElement onChange={(val) => {this.saveValue(val,'input-2')}}/>

Because you will get a value comparison instead of a reference comparison. That way react will always see this property as a new property, forcing a rerender.

var funcCreator = () => () => {};
var funcCreator2 = () => funcCreator;

var isEq = (a, b) => a === b;

isEq(funcCreator(), funcCreator());   // false
isEq(funcCreator2(), funcCreator2()); // true

I wonder why you need the input id at all. Referring to elements sounds a bit of an unnecessary. Anyway, don’t expect to be able to copy/paste this example; and that it will work as is. But this is the general idea:

class MyCustomElement extends Component {
  saveValue = (event) => {
    const { handleSave } = this.props;
    handleSave({ 
      _id: event.target.id, 
      value: event.target.value
    });
  }

  render() {
    return (
      <select onChange={this.saveValue}>
        <option value="lucy">lucy</Option>
      </select>
    );
  }
}

note: you do need babel transform-class-properties for this syntax to work.

Hey,
I think the problem is that they have changed the onChange method here. You don’t receive the event object but only the value:

onChange -> function(value, label)

I just tried it via label prop, but label still was empty on every call.

If I understand the problem correctly, how about passing a second prop into the component

<MyCustomElement onChange={this.saveValue} elem={'input-2'}/>

This way you could call the onChange function with this.props.elem as parameter.

1 Like

Yeah, this seems to work fine, but I guess I’ll run into another problem if I want to set a state value via this.setState, because I didn’t bind to my current component.

In my current case, this isn’t a problem, because I have a store and getting it’s values via properties. But would be interesting to know what would be the correct way to set state while also receiving a function parameter without doing a bind within a prop.

A solution could be:

<MyCustomElement onChange={this.saveValue} elem={'input-2'} current={this}/>

So I’m able to do this.current.setState, but I don’t know if this is a good idea.

I knew that Javascript was a shitty language. But, geeze, this is a new low.

To access state you bind the function in the constructor. Off the top of my head:

class SomeClass extends React.Component {
  constructor(props) {
    super(props);
    this.saveValue = this.saveValue.bind(this);
  }
  saveValue(input) {
    // save, function is bound so has access to `this`
  }
  render() {
    <MyCustomElement onChange={this.saveValue} elem={'input-2'}/>
  }
}

Hey, but then I can’t access the elem property because I got the “wrong” context (because it is binded to the SomeOther class).

Maybe it would be helpful if you posted a more complete example to dig into the code…

Can anyone help me out on this Deployment Failed

Sure, I guess this explains my problem a bit more:

class AdPage extends Component {

saveValue(id, val) {
    this.props.campaign.set(id, val); // Astronomy Object - prop of AdPage
    store.currentCampaign.set(this.props.campaign); // ReactiveVar
}

render() {
  return <Select onChange={this.saveValue} id={'input-2'}/>
}


}

I guess the best way would be to pass the campaign prop to the select element.

return <Select onChange={this.saveValue} id={'input-2'} campaign={this.props.campaign}/>

So I can read the id value and also set the campaign and saving it to the store object.

Because Facebook is explaining you how to get the most out of React? Some performance tweaks are just not really obvious. And perhaps you just don’t care about them for a simple todo app.

You don’t need to follow al the guidelines to start using it. Not feeling comfortable with React? Then don’t use it

Don’t blame the language for a framework or a company that just explains how to use their framework.

Javascript has it’s bads, but this is not one of them. Every language has by value vs by reference.

Yes. But reference versus values are much more explicit in other languages.

In Javascript it’s usually “Hell if I know” when it comes to stuff like this.