使用 onChange 事件传递附加参数
Passing an additional parameter with an onChange event
我想做什么:
我正在尝试将字符串从 child 组件传递到 parent 组件的 handleChange 函数。
当前有效:
我有一个 parent React JS class,方法如下:
handleChange(event) {
console.log(event.target.value);
}
在渲染函数中我有以下内容:
<Child handleChange={this.handleChange.bind(this)} />
在 Child class 我有:
<fieldset onChange={this.props.handleChange}>
<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>
这很好用。
我想做的是:
我正在尝试向 handleChange 函数添加一个 section
参数,如下所示:
handleChange(section, event) {
console.log(section);
console.log(event.target.value);
}
并且在 Child class 我有:
<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>
我现在得到错误:
Uncaught TypeError: Cannot read property 'target' of undefined
在我的第二个 console.log 语句中抛出了这个错误。
我做错了什么?
此外,我正在考虑将 section
参数设为可选。如果是这样,有没有简单的方法可以做到这一点?如果事件参数需要放在最后,似乎是不可能的。
当你写这篇文章时:
<fieldset onChange={this.props.handleChange("tags")}>
handleChange
将在渲染被触发后立即调用。
相反,这样做:
<fieldset onChange={(e) => this.props.handleChange("tags", e)}>
现在 handleChange
将在调用 onChange
处理程序时被调用。
你可以这样做:
<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>
为了将参数从子组件传递到父组件,您可以将参数传递给箭头函数。
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>
示例片段
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>
作为 OP,我最初 post 编辑了这个作为我的问题的后续,但它被删除了,我被告知 post 它作为答案,所以在这里是:
根据 Ritesh Bansal 的回答,我了解到以下内容:
以下行不起作用,因为在函数名称后使用括号时,会立即调用该函数,而不是等待更改发生:
<fieldset onChange={this.props.handleChange("tags")}>
上面的方法行不通,像这样的函数也行不通:
<fieldset onChange={this.props.handleChange()}>
上面的代码也会在第一次渲染时立即被调用。
有两种解决方法:
不太好的方法:
<fieldset onChange={this.props.handleChange.bind(this, "tags")}>
更好的方法:
<fieldset onChange={(evt) => this.props.handleChange("tags", evt)}>
问题已解决。谢谢大家!
更新:
我还研究了 Shubham Khatri 将子元素更改为这样的建议:
<Child handleChange={(e,val) => this.handleChange(e, val)}/>
我没有意识到在 render 函数中使用 bind
,每次调用 render 时都会创建一个新的函数实例。因此,我可以使用 Shubham Khatri 的方法,或者在构造函数中绑定方法。
在你的handle事件中使用双箭头函数,使用箭头函数时不需要绑定:
handleChange = tags => (event) => {
console.log(tags);
console.log(event.target.value);
}
并且在 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>
没有在每个 render() 上定义匿名函数:
这里的大多数答案都推荐在 render() 中定义的匿名函数,正如 Davidicus 指出的那样,不推荐这样做:https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36
François 的回答避免了这个问题,但正如 Vael Victus 指出的那样,这需要 transform-class-properties
。
然而,他所做的只是定义一个定义函数的函数,否则您可以这样做:
constructor(props) {
super(props);
this.handleChange = (yourSpecialParam) => (event) => this.handleChange(yourSpecialParam).bind(this)
}
render() {
return <button onClick={this.handleChange(1234)} >Click Me</button>
}
const handleChange = (tags) => (event) => {
// console.log(tags);
// console.log(event.target.value);
};
<input
type="text"
name="name"
placeholder="Name"
value={input.Iname}
onChange={handleChange("Iname")}
/>
我想做什么:
我正在尝试将字符串从 child 组件传递到 parent 组件的 handleChange 函数。
当前有效:
我有一个 parent React JS class,方法如下:
handleChange(event) {
console.log(event.target.value);
}
在渲染函数中我有以下内容:
<Child handleChange={this.handleChange.bind(this)} />
在 Child class 我有:
<fieldset onChange={this.props.handleChange}>
<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>
这很好用。
我想做的是:
我正在尝试向 handleChange 函数添加一个 section
参数,如下所示:
handleChange(section, event) {
console.log(section);
console.log(event.target.value);
}
并且在 Child class 我有:
<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>
我现在得到错误:
Uncaught TypeError: Cannot read property 'target' of undefined
在我的第二个 console.log 语句中抛出了这个错误。
我做错了什么?
此外,我正在考虑将 section
参数设为可选。如果是这样,有没有简单的方法可以做到这一点?如果事件参数需要放在最后,似乎是不可能的。
当你写这篇文章时:
<fieldset onChange={this.props.handleChange("tags")}>
handleChange
将在渲染被触发后立即调用。
相反,这样做:
<fieldset onChange={(e) => this.props.handleChange("tags", e)}>
现在 handleChange
将在调用 onChange
处理程序时被调用。
你可以这样做:
<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>
为了将参数从子组件传递到父组件,您可以将参数传递给箭头函数。
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>
示例片段
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>
作为 OP,我最初 post 编辑了这个作为我的问题的后续,但它被删除了,我被告知 post 它作为答案,所以在这里是:
根据 Ritesh Bansal 的回答,我了解到以下内容:
以下行不起作用,因为在函数名称后使用括号时,会立即调用该函数,而不是等待更改发生:
<fieldset onChange={this.props.handleChange("tags")}>
上面的方法行不通,像这样的函数也行不通:
<fieldset onChange={this.props.handleChange()}>
上面的代码也会在第一次渲染时立即被调用。
有两种解决方法:
不太好的方法:
<fieldset onChange={this.props.handleChange.bind(this, "tags")}>
更好的方法:
<fieldset onChange={(evt) => this.props.handleChange("tags", evt)}>
问题已解决。谢谢大家!
更新:
我还研究了 Shubham Khatri 将子元素更改为这样的建议:
<Child handleChange={(e,val) => this.handleChange(e, val)}/>
我没有意识到在 render 函数中使用 bind
,每次调用 render 时都会创建一个新的函数实例。因此,我可以使用 Shubham Khatri 的方法,或者在构造函数中绑定方法。
在你的handle事件中使用双箭头函数,使用箭头函数时不需要绑定:
handleChange = tags => (event) => {
console.log(tags);
console.log(event.target.value);
}
并且在 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>
没有在每个 render() 上定义匿名函数:
这里的大多数答案都推荐在 render() 中定义的匿名函数,正如 Davidicus 指出的那样,不推荐这样做:https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36
François 的回答避免了这个问题,但正如 Vael Victus 指出的那样,这需要 transform-class-properties
。
然而,他所做的只是定义一个定义函数的函数,否则您可以这样做:
constructor(props) {
super(props);
this.handleChange = (yourSpecialParam) => (event) => this.handleChange(yourSpecialParam).bind(this)
}
render() {
return <button onClick={this.handleChange(1234)} >Click Me</button>
}
const handleChange = (tags) => (event) => {
// console.log(tags);
// console.log(event.target.value);
};
<input
type="text"
name="name"
placeholder="Name"
value={input.Iname}
onChange={handleChange("Iname")}
/>