0

Is there any performance difference (or other differences that make one better than the other) between

Using arrow functions in render functions:

<SomeElement
    onClick={() => this.updateSalesQuoteProgress(QuotationProgressState.Done)} 
/>

private updateSalesQuoteProgress = (progress: QuotationProgressState): void => {
    this.actionService.updateSalesQuoteProgress(this.props.project, progress);
};

Using partial application in render functions:

<SomeElement
    onClick={this.updateSalesQuoteProgress(QuotationProgressState.Installed)}
/>

private updateSalesQuoteProgress = (progress: QuotationProgressState): (() => void) => {
    return () => {
        this.actionService.updateSalesQuoteProgress(this.props.project, progress);
    };
};

If there is a difference, please explain why

user1283776
  • 19,640
  • 49
  • 136
  • 276
  • Possible duplicate of [Why shouldn't JSX props use arrow functions or bind?](https://stackoverflow.com/questions/36677733/why-shouldnt-jsx-props-use-arrow-functions-or-bind) – Germain Apr 03 '19 at 09:22

1 Answers1

1

In both the cases the returned function is created on every render which affects performance when you have a large application and a lot of such patterns.

The major problem will come when you have nested components as PureComponent or you implement shouldComponentUpdate with shallow comparison of props and when you pass arrow functions as props, the shallow check in PureComponent fails causing performance issues.

Sample demo

class Child extends React.Component {
  shouldComponentUpdate(nextProps) {
    if(this.props.onClick === nextProps.onClick) {
      console.log('same click');
    } else {
      console.log('different click');
    }
    
    if(this.props.onChange === nextProps.onChange) {
      console.log('same change');
    } else {
      console.log('different change');
    }
    return true;
  }
  click = () => {
    this.props.onClick('xyx');
  }
  render() {
    return <button onClick={this.click}>Click</button>
  }
}
class App extends React.Component {
  constructor(props) {
    super(props);
     this.state = {
      count: 0
    }
  }
  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState(prev => ({count: prev.count+ 1}));
    }, 1000)
  }
  handleClick = (id) => (value) => {
    console.log(id, value);
  }
  componentWillUnmount() {
    clearInterval(this.timer);
  }
  handleChange = (val) => {
    console.log(val)
  }
  render() {
    return (
      <div><Child onClick={this.handleClick(1)} onChange={() => this.handleChange(1)} count={this.state.count}/></div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app" />

In order to avoid inline arrow function you can refer this post

How to avoid bind or inline arrow functions inside render method

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400