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?

Cavaleiro das Trevas
fonte
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.

Utsav Patel
fonte
@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;
}
HermitCrab
fonte
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 .

Ben B
fonte
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

Aleh Atsman
fonte
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