私がやろうとしていること:
子コンポーネントから親コンポーネントのhandleChange関数に文字列を渡そうとしています。
現在動作しているもの:
次のメソッドを持つ親React JSクラスがあります。
handleChange(event) {
console.log(event.target.value);
}
レンダリング機能には次のものがあります。
<Child handleChange={this.handleChange.bind(this)} />
Childクラスには次のものがあります。
<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>
これは正常に機能します。
代わりに私がやろうとしていること:
次のように、section
パラメーターをhandleChange関数に追加しようとしています。
handleChange(section, event) {
console.log(section);
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>
私は今エラーを受け取ります:
Uncaught TypeError: Cannot read property 'target' of undefined
このエラーは、2番目のconsole.logステートメントでスローされています。
私は何を間違えていますか?
また、section
パラメーターをオプションにすることを検討しています。もしそうなら、これを行う簡単な方法はありますか?イベントパラメータを最後にする必要がある場合は不可能なようです。
これを書いているとき:
<fieldset onChange={this.props.handleChange("tags")}>
handleChange
は、レンダリングがトリガーされるとすぐに呼び出されます。
代わりに、次のようにしてください:
<fieldset onChange={(e) => this.props.handleChange("tags", e)}>
これで、handleChange
ハンドラーが呼び出されたときにonChange
が呼び出されます。
ハンドルイベントで二重矢印関数を使用すると、矢印関数を使用するときにバインドする必要がありません。
handleChange = tags => (event) => {
console.log(tags);
console.log(event.target.value);
}
そして子供の中で:
<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>
OPとして、私はもともとこれを質問のフォローアップとして投稿していましたが、削除され、代わりに回答として投稿するように言われましたので、ここにあります:
Ritesh Bansalの答えに基づいて、私は次のことを学びました。
関数名の後にかっこを使用すると、変更が発生するのを待つのではなく、関数がすぐに呼び出されるため、次の行は機能しませんでした。
<fieldset onChange={this.props.handleChange("tags")}>
上記は機能せず、次のような機能も機能しません。
<fieldset onChange={this.props.handleChange()}>
上記も最初のレンダリングですぐに呼び出されます。
これには2つの解決策があります。
それほど良くない方法:
<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のメソッドを使用するか、コンストラクターでメソッドをバインドできます。
各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>
}
あなたはこれを行うことができます:
<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>