What I\'m trying to do:
I am trying to pass a string from a child component to the handleChange function of a parent component.
What cur
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>
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>
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>
}
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.
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>