Passing an additional parameter with an onChange event

五迷三道 提交于 2019-12-03 04:48:12

When you are writing this:

<fieldset onChange={this.props.handleChange("tags")}>

handleChange will be called immediately as soon as render is triggered.

Instead, do it like this:

<fieldset onChange={(e) => this.props.handleChange("tags", e)}>

Now the handleChange will be called when onChange handler is called.

In your handle event use double arrow function, there's no need to bind when using arrow function:

handleChange = tags => (event) => {
    console.log(tags);
    console.log(event.target.value);
}

And in the Child:

<fieldset onChange={this.props.handleChange("tags")}>
    <div>Tag 1: <input id="tag1" value={tags[0]} /></div>
    <div>Tag 2: <input id="tag2" value={tags[1]} /></div>
    <div>Tag 3: <input id="tag3" value={tags[2]} /></div>
</fieldset>

As the OP, I had originally posted this as a follow up on my question, but it was deleted and I was told to post it as an answer instead, so here it is:

Based on Ritesh Bansal's answer, I have learned the following:

The following line was not working because when using parenthesis after the function name, the function is called immediately rather than waiting for a change to happen:

<fieldset onChange={this.props.handleChange("tags")}>

The above will not work, neither would a function such as this:

<fieldset onChange={this.props.handleChange()}>

The above would also get called immediately on first render.

There are two solutions to this:

The not-so good way:

<fieldset onChange={this.props.handleChange.bind(this, "tags")}>

The much better way:

<fieldset onChange={(evt) => this.props.handleChange("tags", evt)}>

The problem is now solved. Thank you everyone!

Update:

I also researched Shubham Khatri's suggestion to change the child element to this:

<Child handleChange={(e,val) => this.handleChange(e, val)}/>

I did not realize that using bind in the render function, that every time render is called it creates a new function instance. I can, therefore, either use Shubham Khatri's method, or bind the methods in the constructor.

No anonymous function defined on each render():

Most of the answers here recommend an anonymous function defined in render(), which, as Davidicus pointed out, is not recommended: https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36

François's answer avoids that problem, but as Vael Victus pointed out, that requires transform-class-properties.

However, what he's doing is just defining a function which defines a function, which you can otherwise do like this:

constructor(props) {
  super(props);
  this.handleChange = (yourSpecialParam) => (event) => this.handleChange(yourSpecialParam).bind(this)
}

render() {
  return <button onClick={this.handleChange(1234)} >Click Me</button>
}

You can do this:

<fieldset onChange={(e) => this.props.handleChange("tags", e)}>
    <div>Tag 1: <input id="tag1" value={tags[0]} /></div>
    <div>Tag 2: <input id="tag2" value={tags[1]} /></div>
    <div>Tag 3: <input id="tag3" value={tags[2]} /></div>
</fieldset>

In order to pass a param from the child component to the parent you can take an argument to the arrow function.

handleChange(event, section) {
    console.log(section);
    console.log(event.target.value);
}
<Child handleChange={(e, val) => this.handleChange(e, val)} />

<fieldset onChange={(e) => this.props.handleChange(e, "tags")}>
    <div>Tag 1: <input id="tag1" value={tags[0]} /></div>
    <div>Tag 2: <input id="tag2" value={tags[1]} /></div>
    <div>Tag 3: <input id="tag3" value={tags[2]} /></div>
</fieldset>

Sample snippet

class App extends React.Component {
  handleChange(e, val) {
    console.log(e.target.value, val);
  }
  render() {
    return(
      <Child handleChange={(e,val) => this.handleChange(e, val)}/>
    )
  }
}

class Child extends React.Component {
  
  render() {
    return(
      <input type="text" onChange={(e) => this.props.handleChange(e, 'tab')}/>
    )
  }
}

ReactDOM.render(<App/>, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!