0

After writing a quite large application for the first time with react I've come accross an issue where my re-renders are basically freezing the UI which is so bad for the UX.

I did not know that passing an anonymous function as a prop caused the entire receiving component every time. So now I'm trying to fix my functions but find it quite hard to get right.

So currently I have a component called NavBar which has subcomponents called NavBarLink. Each NavBarLink calls the same showPopup(arg) function. The argument for showPopup(arg) however is based on which NavBarLink is clicked.

Example

render() {
    return (
        <NavBarLink onClick={() => showPopup("UNIQUE_POPUP_ID")}>Link 1</NavBarLink>
        <NavBarLink onClick={() => showPopup("ANOTHER_POPUP_ID")}>Link 2</NavBarLink>
    );
}

Question

How can I have the same developer experience but don't suffer from the re-rendering issues?

Related articles

NealVDV
  • 2,302
  • 3
  • 26
  • 51
  • Perhaps pass in showPopup and the popup id as two separate props, and at the appropriate time have the NavBarLink component call `this.props.showPopup(this.props.popupId) – Michael Horn Oct 04 '17 at 13:59
  • check this answer https://stackoverflow.com/questions/45053622/how-to-avoid-binding-inside-render-method/45053753#45053753 – Shubham Khatri Oct 04 '17 at 14:18

1 Answers1

3

To stop the function being created on each render, you can define them as class methods, and pass the IDs as props to each NavBarLink

class MyComponent {
  handleClick = (id) => {
    return showPopup(id)
  }

  render () {
    return (
      <div>
        <NavBarLink onClick={this.handleClick} id='UNIQUE_POPUP_ID'>Link 1</NavBarLink>
        <NavBarLink onClick={this.handleClick} id='ANOTHER_POPUP_ID'>Link 2</NavBarLink>
      </div>
    )
  }
}

then in your NavBarLink class, you add another method to call the handler with the ID passed in the props.

class NavBarLink {
  handleClick = () => {
    this.props.onClick(this.props.id)
  }

  render () {
    return (
      <a onClick={this.handleClick}>...</a>
    )
  }
}

I hope I interpreted your question correctly!

Alex Bass
  • 2,262
  • 1
  • 13
  • 16
  • Thanks, but this is like 6 lines of code more for a simple argument pass to the onClick function, to me this seems so much boilerplate no? – NealVDV Oct 04 '17 at 14:22
  • I think it's the simplest way of ensuring the callback is only created once, short of using a `memoize` function or similar. To be honest there are probably other places you can optimise your code, unless this is being called like 23957923 times a second – Alex Bass Oct 04 '17 at 16:32