web-dev-qa-db-ja.com

React子コンポーネントの矢印関数でパラメーターを渡す

これらの親コンポーネントと子コンポーネントがあります。クリック機能を渡して、子コンポーネントのアイテムを選択します。それでも、ユーザーが要素をクリックするまで待つのではなく、子コンポーネントの関数が自動的に呼び出されるようです。わかりやすくするために、ここに私の親と子のコンポーネントがあります

export class ParentView extends Component {
  state = {
    selectedItem: {}
  }

  handleClick = (item) => {
    alert('you click me');
    this.setState({selectedItem: item});
  } 

  render() {
    let item = { name: 'Item-1' };
    return (
      <div>
        <ChildItem item={item} handleClick={this.handleClick} />
      </div>
    );
  }
}

export class ChildItem extends Component {
  render() {
    const {item, handleClick} = this.props;
    return (
      <div>
        <a  onClick={handleClick(item)} />
      </div>
    );
  }
}

これらは、アロー関数を使用してhandleClickを子コンポーネントに渡す私のコンポーネントですが、ユーザーによってトリガーされることなく、最初のレンダリング時に常にアラートが呼び出されます。なにか提案を?

8
Dion Dirza

渡された関数呼び出しの結果ではなく、関数自体をonClickに渡す必要があります。

Paramで呼び出したい場合は、オプションがあります。

  • itemhandleClick.bind(this, item)でバインドします。 bindは、事前定義された最初のパラメーターを持つ新しい関数を作成します-item
  • _() => handleClick(item)_のような新しい矢印関数を渡す

以下の例:

_export class ChildItem extends Component {
  render() {
    const { item, handleClick } = this.props;

    return (
      <div>
        <a onClick={() => handleClick(item)} />
      </div>
    )
  }
}
_

コードでは、onClick宣言で関数を呼び出しているため、handleClickの実行結果はonClickに渡されます。 。

<a onClick={handleClick(item)} />

更新:

@dhiltが書いたように、そのようなアプローチには欠点があります。新しく作成されたアロー関数と_.bind_も、renderChildItemメソッドが呼び出されるたびに新しい関数を作成するため、reactは、 renderメソッドの以前の「キャッシュされた」結果、つまり将来的にいくつかのパフォーマンスの問題が発生する可能性があることを意味します。この問題に関する eslint のルールさえありますが、 2つのポイントがあるため、このルールに従うだけではありません。

1)_performance problems_を測定する必要があります。 forは同じまたは「高速」であるため、通常のforを優先して_Array.prototype.forEach_を使用することを禁止しません。

2)クラスプロパティとしてクリックハンドラーを定義すると、コンポーネントインスタンスの初期化ステップが増加します。再レンダリングは反応が速く効率的であるため、最初のレンダリングの方が重要な場合があります。

ちょうどあなたのために良いものを使用し、おそらくこのような記事を読んでください https://cdb.reacttraining.com/react-inline-functions-and-performance-bdff784f5578

12
uladzimir

承認された回答にはパフォーマンスヒットがあります。各レンダーが新しい関数を割り当てるため、データが変更されていなくても、ChildItemコンポーネントは再レンダリングされます(.bind;アロー関数と同じ)。この特定の場合、ハンドラーとその引数を新しいパブリッククラスフィールドのpropsから直接取得することで、このような問題を回避するのは非常に簡単です。

export class ChildItem extends Component {

  onClick = () => {
    this.props.handleClick(this.props.item);
  }

  render() {
    return (
      <div>
        <a  onClick={this.onClick} />
      </div>
    );
  }
}

ParentViewはそのままです。

3
dhilt

ES6方法:

矢印関数の使用=>

onClick={() => handleClick(item)}

(@havenchykの答えはES5の方法です)。

2
Snowman