Лучший способ передать параметры в обработчике onClick

10

Это мой компонент, я использую встроенную функцию стрелки, чтобы изменить маршрут 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. Если я уберу функцию стрелки, то функция вызывается на самом рендере.

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>
    </>
  )
}

Тогда как я могу продолжить с лучшими способами передачи параметров?

Темный рыцарь
источник
Вероятно, стоит отметить, что причина, по которой использование встроенных функций стрелок здесь "не является хорошим способом с точки зрения производительности", заключается не в том, что функции стрелок как-то по своей природе будут выполняться медленно (они не являются, и в любом случае Стоимость вызова функции совершенно незначительна для чего-то, что редко выполняется как обработчик щелчков), но потому что React будет создавать новые экземпляры функций каждый раз, когда компонент будет перерисован. Встроенное связывание имеет точно такую ​​же проблему. И в любом случае это нормально, если только компонент не перерисовывается очень часто.
Ильмари Каронен
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если вы определите обработчик, как я опубликовал.
Утсав Патель
Пожалуйста, проверьте это
Темный рыцарь
@DarkKnight Пожалуйста, прочитайте этот activjs.org/docs/handling-events.html Синтаксис поля класса является одним из рекомендуемых методов в официальных документах реагирования.
Утсав Патель
Хорошо, спасибо, сэр
Темный рыцарь
3

Вы можете добавить данные в свой div:

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

Затем вы можете получить эти данные в вашем обработчике onClick:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}
Рак-Отшельник
источник
Ха-ха-ха ... Может быть сделано. Но сам реагировать не имеет обходной путь?
Темный рыцарь
1

№ 1 в порядке.

# 2 тоже «хорошо», но вам нужно пропустить реквизиты, тогда функция рендеринга будет выглядеть точно так же, как # 1 . Вы будете вызывать bindфункцию 'd, потому что вы заменили ее в конструкторе.

№ 3 просто неверен, так как функция вызывается во время рендеринга.

И что касается № 4, отреагировать документы

Мы обычно рекомендуем связывание в конструкторе или использование синтаксиса полей класса, чтобы избежать такого рода проблем с производительностью.

Это приводит к снижению производительности, когда ваша функция используется в ее дочерних компонентах, и вызывает повторное рендеринг дочерних компонентов (это не в вашем случае). Так что вы не должны делать № 4 .

Бен Б
источник
1

Лучший способ в настоящее время - обернуть ваш обработчик событий в useCallbackловушку, поскольку он будет препятствовать созданию вашей функции обработчика при каждом вызове render.

import React, { useCallback } from 'react'

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

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

Для получения дополнительной информации проверьте - используйте Обратные документы

Олег Атсман
источник
Похоже, что OP использует компонент класса, где вы не можете использовать хуки.
TJ Crowder
Я надеюсь, что мой ответ поможет ему понять лучший путь
Олег Атсман