admin管理员组

文章数量:1200772

I am using inline arrow function to change the onClick handlers of some divs in my React component, but I know it is not a good way in terms of performance.

Objectively, what is the most efficient way of setting onClick handlers that require arguments? This is what I have tried:

1. Inline arrow function

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

2. If I use constructor binding then how can I pass props?

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. If I remove the arrow function then the function being called on the render itself

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

4. If I use inline binding then it is also not best with performance

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

Then how can I proceed with the best way passing parameters?

I am using inline arrow function to change the onClick handlers of some divs in my React component, but I know it is not a good way in terms of performance.

Objectively, what is the most efficient way of setting onClick handlers that require arguments? This is what I have tried:

1. Inline arrow function

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

2. If I use constructor binding then how can I pass props?

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. If I remove the arrow function then the function being called on the render itself

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

4. If I use inline binding then it is also not best with performance

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

Then how can I proceed with the best way passing parameters?

Share Improve this question edited May 8, 2020 at 10:42 Ryan M 20.1k34 gold badges73 silver badges82 bronze badges asked Apr 14, 2020 at 9:14 Dark KnightDark Knight 1,0836 gold badges26 silver badges50 bronze badges 2
  • 1 It's probably worth noting that the reason why using inline arrow functions here "is not [a] good way in terms of performance" isn't because arrow functions would somehow be intrinsically slow to run (they're not, and in any case the cost of a function call is totally negligible for something as rarely executed as a click handler) but because React will create new instances of the functions every time the component is re-rendered. Inline binding has the exact same issue. And it's usually fine anyway, unless the component gets re-rendered very frequently. – Ilmari Karonen Commented Apr 14, 2020 at 18:14
  • 2 @IlmariKaronen In most of the cases component re-renders frequently because the components have input field and typing & setting the e.target.value in state result in frequent render. – Dark Knight Commented Apr 15, 2020 at 5:14
Add a comment  | 

5 Answers 5

Reset to default 6

You can use arrow function to define your changeRoute handler.

This is known as Class field syntax. More on it here in official react docs.

constructor() {
  super(props)
}

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

Then you can use this function directly like so:

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

You do not have to worry about the binding. Arrow functions inherit their parent's this.

You can add a data to your div:

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

Then you can retrieve that data in your onClick handler:

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

#1 is fine.

#2 is also 'fine', but you need to pass props, then the render function will look exactly like #1. You will be calling the bind'd function, because you replaced it in the constructor.

#3 is just wrong, as the function gets called during render.

And regarding #4, from react docs

We generally recommend binding in the constructor or using the class fields syntax, to avoid this sort of performance problem.

This causes a performance penalty when your function is used in its child components and will cause the child components to re-render (its not in your case). So you shouldn't do #4.

The best way currently is to wrap your event handler in useCallback hook as it will prevent your handler function from being created each time render is called.

import React, { useCallback } from 'react'

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

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

For more info check - useCallback docs

Below is another way to read parameter. Here you don't need to create another function inside the arrow function to pass parameter.

const Simple = () => {
    
    const handleClick = (e) => {
      e.preventDefault()
      let id = e.target.getAttribute('data-id')
      console.log(id) // prints hello
      console.log('This is handle click')
    }
    
    return (
      <>
        <a onClick={handleClick} data-id='hello'>Click here</a>
      </>
    )
    
    }

本文标签: javascriptMost efficient way to pass parameters in onClick handlerStack Overflow