web-dev-qa-db-ja.com

onChangeイベントで追加のパラメーターを渡す

私がやろうとしていること:

子コンポーネントから親コンポーネントの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パラメーターをオプションにすることを検討しています。もしそうなら、これを行う簡単な方法はありますか?イベントパラメータを最後にする必要がある場合は不可能なようです。

19
kojow7

これを書いているとき:

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

handleChangeは、レンダリングがトリガーされるとすぐに呼び出されます。

代わりに、次のようにしてください:

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

これで、handleChangeハンドラーが呼び出されたときにonChangeが呼び出されます。

37
Ritesh Bansal

ハンドルイベントで二重矢印関数を使用すると、矢印関数を使用するときにバインドする必要がありません。

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のメソッドを使用するか、コンストラクターでメソッドをバインドできます。

3
kojow7

各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>
}
2
kalzen

あなたはこれを行うことができます:

<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>
1
Omri Aharon

子コンポーネントから親にパラメーターを渡すために、矢印関数への引数を取ることができます。

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>
1
Shubham Khatri