Source:  Twitter logo

I found in legacy code

componentDidMount = () => {
...
}

I know it is not valid, but it works. Now, I am curious what is the difference between this, and the right way

componentDidMount() {
...
}

Hi basically you can do it, but it's unnecessary and can also hurt performance. Because each time your function does an arrow operation, it has to create a new function object. So it's just an optimization choice.

Good threads and articles:

8 users liked answer #0dislike answer #08
igorves profile pic
igorves

I don't think there is much difference.

But () => {} returns something (implicitly), and I don't think componentDidMount() returns something nor would it be 'better'

So I would write this (as in the docs)

componentDidMount() {
...
}
0 users liked answer #1dislike answer #10
Victor Jozwicki profile pic
Victor Jozwicki

Arrow functions and function declarations in React work the same way as how they work in vanilla JS.

componentDidMount = () => { // arrow function

and

componentDidMount() { // function declaration

mean the same as these functions are class specific in React. But things get interesting when you see how arrow functions and function declarations behave when you create them and pass them as handlers to other components.

Take a look at this example

export default class Parent extends Component {
  constructor() {
    super();
    this.state = {
      time: new Date().toLocaleTimeString()
    };

    // no function binding necessary

  }

  updateTime = () => { // arrow function used here
    this.setState({ // `this` here will be bound to Parent implicitely
      time: new Date().toLocaleTimeString()
    });
  };

  render() {
    return (
      <div>
        <div>Parent: {this.state.time}</div>
        <button onClick={() => this.updateTime()}>Button in Parent</button>
        <Child
          time={new Date().toLocaleTimeString()}
          updateTimeHandler={this.updateTime}
        />
      </div>
    );
  }
}

// updateTimeHandler will be implicitly bound
// to Parent's context
const Child = ({ time, updateTimeHandler }) => {
  return (
    <div>
      <div>Child: {time}</div>
      <button onClick={() => updateTimeHandler()}>Button in Child</button>
    </div>
  );
};

export default Child;

Now when you don't use arrow,

export default class Parent extends Component {
  constructor() {
    super();
    this.state = {
      time: new Date().toLocaleTimeString()
    };
    // you have to bind the function to this class
    // if you don't, then `this.` in the method
    // will execute in child's context and throw an error
    this.updateTime = this.updateTime.bind(this);
  }

  updateTime() { // function declaration
    this.setState({
      time: new Date().toLocaleTimeString()
    });
  }

  render() {
    return (
      <div>
        <div>Parent: {this.state.time}</div>
        <button onClick={() => this.updateTime()}>Button in Parent</button>
        <Child
          time={new Date().toLocaleTimeString()}
          updateTimeHandler={this.updateTime}
        />
      </div>
    );
  }
}

// updateTimeHandler will execute in Parent's context
// as we explicitly told so
const Child = ({ time, updateTimeHandler }) => {
  return (
    <div>
      <div>Child: {time}</div>
      <button onClick={() => updateTimeHandler()}>Button in Child</button>
    </div>
  );
};

export default Child;

You can play around in this code sandbox and see it for yourself.

https://codesandbox.io/s/j78y87npkv

In addition to this behavior, there are obvious performance differences as quoted in other answers.

0 users liked answer #2dislike answer #20
Dinesh Pandiyan profile pic
Dinesh Pandiyan

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).