onClickハンドラーでパラメーターを渡す最良の方法


11

これは私がインライン矢印機能を使用してonClickdiv のルートを変更している私のコンポーネントですが、パフォーマンスの点で良い方法ではないことを知っています

1.インライン矢印関数

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={() => this.changeRoute("page1")}>1</div>
      <div onClick={() => this.changeRoute("page2")}>2</div>
    </>
  )
}

2.コンストラクターバインディングを使用する場合、小道具をどのように渡すことができますか?

constructor() {
  super(props)
  this.changeRoute = this.changeRoute.bind(this)
}
changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute}>1</div>
      <div onClick={this.changeRoute}>2</div>
    </>
  )
}

3. arrow関数を削除すると、レンダリング自体で呼び出されている関数

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute("page1")}>1</div>
      <div onClick={this.changeRoute("page2")}>2</div>
    </>
  )
}

4.インラインバインディングを使用する場合、パフォーマンスも最適ではありません

changeRoute (routeName) {
  console.log(routeName)
}
render() {
  return (
    <>
      <div onClick={this.changeRoute.bind(this, "page1")}>1</div>
      <div onClick={this.changeRoute.bind(this, "page2")}>2</div>
    </>
  )
}

次に、パラメータを渡す最善の方法をどのように進めることができますか?


ここでインライン矢印関数を使用する理由が「パフォーマンスの点で[a]良い方法ではない」というのは、矢印関数の実行が本質的に遅いためです(そうではありません。関数呼び出しのコストは、クリックハンドラーとして実行されることはほとんどありませんが、コンポーネントが再レンダリングされるたびに関数の新しいインスタンスが作成されるため、まったく無視できます。インラインバインディングにもまったく同じ問題があります。そして、コンポーネントが非常に頻繁に再レンダリングされない限り、通常はとにかく問題ありません
Ilmari Karonen

2
@IlmariKaronenほとんどの場合、コンポーネントには入力フィールドがあり、状態でe.target.valueを入力および設定すると頻繁にレンダリングされるため、コンポーネントは頻繁に再レンダリングされます。
ダークナイト

回答:


6

アロー関数を使用してchangeRouteハンドラーを定義できます。

これはとして知られていClass field syntaxます。詳細については、公式の反応ドキュメントをご覧ください

constructor() {
  super(props)
}

const changeRoute = (parameter) => (event) => {
    // business logic for route change.
}

次に、この関数を直接次のように使用できます。

render() {
  return (
    <>
      <div onClick={changeRoute(params1)}>1</div>
      <div onClick={changeRoute(params2)}>2</div>
    </>
  )
}

バインディングについて心配する必要はありません。アロー関数は親のを継承しthisます。


@DarkKnight最後のコメントはでしたexecuting on the go。私の答えはそれに応えるものです。私execute on the goが投稿したようなハンドラーを定義した場合、クリックハンドラーは機能しないことを伝えようとしています。
Utsav Patel


@DarkKnightこちらをお読みくださいreactjs.org/docs/handling-events.htmlクラスフィールドの構文は、公式の反応ドキュメントで推奨される方法の1つです。
Utsav Patel

わかりました、ありがとうございます
ダークナイト

3

divにデータを追加できます。

<div data-id={1} onClick={this.changeRoute}>1</div>

次に、onClickハンドラーでそのデータを取得できます。

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}

素晴らしいアプローチ!
最大

はははは...できる。しかし、反応自体は回避策を持っていませんか?
ダークナイト

1

#1で結構です。

#2も「問題ありません」が、propsを渡す必要がある場合、render関数は#1とまったく同じように見えます。bindコンストラクターで置き換えたため、'd関数を呼び出します。

#3は間違っています。レンダリング中に関数が呼び出されるためです。

そして#4に関しては、反応ドキュメントから

この種のパフォーマンスの問題を回避するには、通常、コンストラクターでバインドするか、クラスフィールド構文を使用することをお勧めします。

これにより、子コンポーネントで関数が使用されるとパフォーマンスが低下し、子コンポーネントが再レンダリングされます(ケースではありません)。したがって、#4を行うべきではありません。


1

現在のところ、useCallbackレンダリングが呼び出されるたびにハンドラー関数が作成されないようにするため、イベントハンドラーをフックでラップすることが最善の方法です。

import React, { useCallback } from 'react'

const MyComponent = ({ changeRoute }) => {
  const eventHandler = useCallback(() => {
    changeRoute('page1')
  }, [changeRoute])

  return (
    <div onClick={eventHandler}>1</div>
  )
}

詳しくはこちらをご覧ください-useCallback docs


OPは、フックを使用できないクラスコンポーネントを使用しているように見えます。
TJクラウダー

私の答えが彼がより良い方法を理解するのに役立つことを願っています
Aleh Atsman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.