7

I would like to know if, in React.js, there is a performance difference between declaring an anonymous function, a named function, or a method within a component.

Concretely, is one of the following more performant than the others?

class MyComponent extends React.Component {
  render() {
    return (
      <input
        type="text"
        value={foo}
        onChange={(e) => {
          this.setState({ foo: e.target.value });
        }}
      />
    );
  }
}

class MyComponent extends React.Component {
  ...
  render() {
    function handleChange(e) {
      this.setState({ foo: e.target.value });
    }
    return (
      <input
        type="text"
        value={foo}
        onChange={handleChange}
      />
    );
  }
}

class MyComponent extends React.Component {
    ...
    handleChange(e) {
      this.setState({ foo: e.target.value });
    }

    render() {
      return (
        <input
          type="text"
          value={foo}
          onChange={this.handleChange}
        />
      );
    }

}

2 Answers 2

8

Yes there most certainly is, The third version of you're code is the correct way of referencing a function within the Render block of a react component.

Why?

Generally nesting functions is considered an anti-pattern for methods that will be called more than once or twice; This is due primarily to the fact the javascript engine sees functions as any other value and must create & then subsequently destroy it after the parent call has completed.

If you need to be able to access this from within handleChange() you need to bind the method to the context of the component. The following are the methods that would not result in any negative performance impact.

Vanilla ES6 via constructor:

class MyComponent extends React.Component {
    constructor(props) {
        super(props)
        this.handleChange = this.handleChange.bind(this)
    }

    handleChange(e) {
        this.setState({ foo: e.target.value });
    }

    render() {
        return (
            <input
                type="text"
                value={foo}
                onChange={this.handleChange}
            />
        )
    }
}

Arrow function in Class Property (requires babel w/ transform-class-properties):

class MyComponent extends React.Component {
    handleChange = (e) => {
        this.setState({ foo: e.target.value });
    }

    render() {
        return (
            <input
                type="text"
                value={foo}
                onChange={this.handleChange}
            />
        )
    }
}

Decorated Class method (requires babel w/ transform-decorators-legacy and core-decorators):

import { autobind } from 'core-decorators'

class MyComponent extends React.Component {

    @autobind
    handleChange(e) {
        this.setState({ foo: e.target.value });
    }

    render() {
        return (
            <input
                type="text"
                value={foo}
                onChange={this.handleChange}
            />
        )
    }
}

Hope this helps!

Sign up to request clarification or add additional context in comments.

1 Comment

I wish JavaScript wasn't so messy
5

The third option is best. You want to avoid setting state setState({}) inside your render function because it is no longer 'pure'. This is a term people use when talking about functional programming. It basically means there are no side-effects. Even though you aren't calling those functions with setState immediately in the render function, I think it's still best to pull that logic outside and get into the habit of thinking about pure functions.

Pure Functions A pure function is a function which: Given the same input, will always return the same output. Produces no side effects. Relies on no external mutable state.

Also considering performance, you are creating a new function every time the render function runs. You only need to create these functions once so it's best to pull them outside.

How often does the render function run? It can be quite a lot! Every time you change state or pass new props from parent component.

5 Comments

I would add that options 1 and 2 also create a new function on every render which is inefficient, which is the reasoning the OP is looking for.
Yep, you don't need to be creating these functions more than once.
all 3 render methods are completely equivalent in terms of function purity - none of them are pure (because of using this), and the onChange prop contains a value of the same type (function) in all 3 cases... 2nd and 3rd option won't even work without proper binding (as in the Luigi's answer) so comparing performance is slightly misleading
This answer is incorrect. As @Aprillion mentions, all three examples are pure functions. The second example, with the named function won't even create a new reference for handleChange. The anonymous function in the first example will get a new reference each render. But I believe modern JavaScript engines will tend to optimize that away.
Thank you for this! I recently learned this and you explained this for me so much more

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.