Melhor maneira de passar parâmetros no manipulador onClick


11

Este é o meu componente. Estou usando a função de seta embutida para alterar a rota onClickda div, mas sei que não é uma boa maneira em termos de desempenho

1. Função de seta embutida

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

2. Se eu uso a ligação de construtor, como posso transmitir adereços?

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. Se eu remover a função de seta, a função que está sendo chamada na própria renderização

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

4. Se eu usar a ligação embutida, também não será o melhor desempenho

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

Então, como posso proceder com a melhor maneira de passar parâmetros?


Provavelmente, vale a pena notar que a razão pela qual o uso de funções de seta embutida aqui "não é [um] bom caminho em termos de desempenho" não é porque as funções de seta seriam intrinsecamente lentas para executar (elas não são e, de qualquer forma, o o custo de uma chamada de função é totalmente desprezível por algo tão raramente executado como um manipulador de cliques), mas porque o React criará novas instâncias das funções toda vez que o componente for renderizado novamente. A ligação embutida tem exatamente o mesmo problema. E geralmente é bom de qualquer maneira, a menos que o componente seja renderizado novamente com muita frequência.
Ilmari Karonen 14/04

2
@IlmariKaronen Na maioria dos casos, o componente é renderizado frequentemente porque os componentes têm campo de entrada e digitando e definindo o e.target.value no estado resultam em renderizações frequentes.
Dark Knight

Respostas:


6

Você pode usar a função de seta para definir seu changeRoutemanipulador.

Isso é conhecido como Class field syntax. Mais sobre isso aqui nos documentos oficiais de reação.

constructor() {
  super(props)
}

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

Então você pode usar esta função diretamente da seguinte maneira:

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

Você não precisa se preocupar com a ligação. As funções de seta herdam as de seus pais this.


@DarkKnight Seu último comentário foi executing on the go. Minha resposta é em resposta a isso. Estou tentando lhe dizer que seu manipulador de cliques não o fará execute on the gose você definir o manipulador como eu publiquei.
Utsav Patel 14/04

Pls verificar isso
Dark Knight

@DarkKnight Leia este reactjs.org/docs/handling-events.html A sintaxe do campo de classe é um dos métodos recomendados pelos documentos oficiais do react.
Utsav Patel 14/04

ok obrigado senhor
Dark Knight

3

Você pode adicionar dados à sua div:

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

Em seguida, você pode recuperar esses dados em seu manipulador onClick:

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

Abordagem brilhante!
Max

Ha ha ha ... Pode ser feito. Mas a reação em si não tem solução?
Dark Knight

1

# 1 está bem.

# 2 também é 'bom', mas você precisa passar adereços, então a função de renderização será exatamente igual a # 1 . Você estará chamando a bindfunção 'd, porque a substituiu no construtor.

# 3 está errado, pois a função é chamada durante a renderização.

E em relação ao item 4, de reagir documentos

Geralmente, recomendamos a ligação no construtor ou o uso da sintaxe dos campos de classe, para evitar esse tipo de problema de desempenho.

Isso causa uma penalidade no desempenho quando sua função é usada em seus componentes filhos e fará com que os componentes filhos sejam renderizados novamente (não é o seu caso). Então você não deve fazer o # 4 .


1

Atualmente, a melhor maneira é envolver o manipulador de eventos no useCallbackgancho, pois isso impedirá que a função do manipulador seja criada toda vez que a renderização for chamada.

import React, { useCallback } from 'react'

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

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

Para obter mais informações, verifique - useCallback docs


O OP parece estar usando um componente de classe, no qual você não pode usar ganchos.
TJ Crowder

Espero que minha resposta o ajude a entender a melhor maneira
Aleh Atsman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.