La mejor manera de pasar parámetros en el controlador onClick

10

Este es mi componente. Estoy usando la función de flecha en línea para cambiar la ruta onClickde div, pero sé que no es una buena manera en términos de rendimiento.

1. Función de flecha en línea

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

2. Si uso el enlace de constructor, ¿cómo puedo pasar accesorios?

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. Si elimino la función de flecha, entonces la función que se llama en el render en sí

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

4. Si uso el enlace en línea, entonces tampoco es mejor con el rendimiento

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

Entonces, ¿cómo puedo proceder con la mejor manera de pasar parámetros?

Caballero oscuro
fuente
Probablemente valga la pena señalar que la razón por la cual el uso de funciones de flecha en línea aquí "no es [una] buena manera en términos de rendimiento" no se debe a que las funciones de flecha de alguna manera serían intrínsecamente lentas de ejecutar (no lo son, y en cualquier caso el el costo de una llamada a la función es totalmente insignificante para algo que rara vez se ejecuta como un controlador de clics), pero debido a que React creará nuevas instancias de las funciones cada vez que se vuelva a representar el componente. El enlace en línea tiene exactamente el mismo problema. Y generalmente está bien de todos modos, a menos que el componente se vuelva a representar con mucha frecuencia.
Ilmari Karonen
2
@IlmariKaronen En la mayoría de los casos, el componente se vuelve a procesar con frecuencia porque los componentes tienen un campo de entrada y al escribir y establecer el valor e.target.value en el estado se traduce en un procesamiento frecuente.
Dark Knight

Respuestas:

6

Puede usar la función de flecha para definir su changeRoutecontrolador.

Esto se conoce como Class field syntax. Más información aquí en documentos oficiales de reacción.

constructor() {
  super(props)
}

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

Entonces puede usar esta función directamente así:

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

No tiene que preocuparse por el enlace. Las funciones de flecha heredan las de sus padres this.

Utsav Patel
fuente
@DarkKnight Tu último comentario fue executing on the go. Mi respuesta es en respuesta a eso. Estoy tratando de decirle que su controlador de clics no lo hará execute on the gosi define el controlador como lo he publicado.
Utsav Patel
Por favor revisa esto
Dark Knight
@DarkKnight Lea esto reactjs.org/docs/handling-events.html La sintaxis del campo de clase es uno de los métodos recomendados por los documentos oficiales de reacción.
Utsav Patel
ok gracias señor
Caballero Oscuro
3

Puede agregar datos a su div:

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

Luego puede recuperar esos datos en su controlador onClick:

onClick = (event) => {
  const id = event.currentTarget.dataset.id;
}
Cangrejo ermitaño
fuente
Enfoque brillante!
Max
Ja, ja, ja ... Se puede hacer. Pero la reacción a sí mismo no tiene solución?
Dark Knight
1

# 1 está bien.

# 2 también está 'bien', pero necesita pasar accesorios, entonces la función de renderizado se verá exactamente como # 1 . Llamarás a la bindfunción 'd, porque la reemplazaste en el constructor.

# 3 está mal, ya que la función se llama durante el render.

Y con respecto al n. ° 4, de reaccion docs

En general, recomendamos vincular en el constructor o utilizar la sintaxis de los campos de clase para evitar este tipo de problema de rendimiento.

Esto causa una penalización de rendimiento cuando su función se usa en sus componentes secundarios y hará que los componentes secundarios se vuelvan a representar (no es en su caso). Entonces no deberías hacer el # 4 .

Ben B
fuente
1

La mejor manera actualmente es envolver su controlador de eventos en useCallbackgancho, ya que evitará que se cree su función de controlador cada vez que se llame render.

import React, { useCallback } from 'react'

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

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

Para obtener más información, consulte: use los documentos de Callback

Aleh Atsman
fuente
El OP parecería estar usando un componente de clase, donde no puedes usar ganchos.
TJ Crowder
Espero que mi respuesta lo ayude a entender la mejor manera
Aleh Atsman