1

Say I have a class component called 'Parent' which renders a component called 'Child':

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            someProperty = 'some value',
        };
}

setProperty: newValue => {
    this.setState({someProperty: newValue});
}

render() {
    return < Child setProperty: {this.setProperty} />
}

and the Child component:

const Child = props => {
    return <button onClick={props.setProperty('new value')} />
}

So this works, and it makes sense to me: We're passing a reference to setProperty, which is then whenever a child component is clicked.

In many tutorials, I see the following code (in Parent):

render() {
    return < Child setProperty: {newValue => this.setProperty(newValue) />
}

Is there a benefit to doing this when passing a function along?

fishamit
  • 217
  • 2
  • 9
  • The code in the child is wrong but I guess that's not relevant to the question. – Felix Kling Jun 22 '18 at 00:51
  • If the parent re renders, it'll FORCE the child to re-render due to a change in props since the inline function will be redefined(may have changed in 16 though). So yeah it matters, but it depends. If the parents doesn't re render automatically and only on interaction, then not much difference exists between the two. But if there is heavy async fetching and reloading on the page it cause more rending than if you used the bound function or pre defined function, which could lead to a lot of load especially if you cascade that function a lot – Robert Mennell Jun 22 '18 at 01:28

2 Answers2

2

Is there a benefit to doing this when passing a function along?

It depends on how this.setProperty is defined. It is either unnecessary to do it that way or necessary** because it wouldn't work otherwise.

It all comes down to how this works:

In "normal" functions, the value of this depends on how the function is called. So if this.setProperty is such a normal function, then passing it to the child with setProperty={this.setProperty} makes it impossible for the child to call the function so that this refers to the parent component, which means calling this.setState inside the function will fail.

function callMe(callback) {
  callback();
}

const obj = {
  foo: 42,
  normalFunction() {
    console.log(this.foo);
  },
};

callMe(obj.normalFunction); // not 42 :(
callMe(() => obj.normalFunction()); // 42 :)

But if the function is an arrow function (like in your first example) or a bound function then the value of this is already predetermined and it doesn't matter how the function is called.

function callMe(callback) {
  callback();
}

const obj = {
  foo: 42,
  normalFunction() {
    console.log(this.foo);
  },
};
obj.boundFunction = obj.normalFunction.bind(obj);

callMe(obj.boundFunction); // 42 :)
callMe(() => obj.boundFunction()); // 42 :)

Related:

--

**: Of course it is not "necessary" to pass the function in any specific way if one can control how the function is defined. This whole answer is only looking at why someone might be doing it this way. You can avoid a certain style if you change how the function is defined.

Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
1

So there’s been some controversial discussions about inline functions. Many believe inline functions are not performant and also make the child components re-render cause of different reference of functions specially in case of using PureComponent.

IMHO to me there is no difference but why not using static functions while they’re available in a any case

This is just an example that demonstrates difference between using a static function and inline functions:

class Test extends Component {
  render() {
    return(
      <button onClick={() => this.props.onUpdate(true)}>update</button>
    )
  }
}

// could be this as handleClick is the same reference in all renders
class Test2 extends Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.props.onUpdate(true);
  }
  render() {
    return (
      <button onClick={this.handleClick}>update</button>
    );
  }
}

Update: Used constructor to bind the static function

Amin Paks
  • 268
  • 1
  • 11
  • *"why not using static functions while they’re available in a any case*" Worth nothing that these syntax is not official part of the language yet. Depending on the build process someone has they may or may not be able to define functions this way. Of course there are also ways to avoid inline functions without this syntax... – Felix Kling Jun 22 '18 at 01:14
  • What do you mean they’re not part of official language? – Amin Paks Jun 22 '18 at 01:16
  • The `x = y;` syntax in class bodies is a *proposal* for the language, but it is not officially part of it yet: See "Class Public Instance Fields & Private Instance Fields" in https://github.com/tc39/proposals . You won't find the syntax [in the latest spec (2017)](http://ecma-international.org/ecma-262/8.0/index.html) and not in this year's spec either. – Felix Kling Jun 22 '18 at 01:18
  • Updated accordingly – Amin Paks Jun 22 '18 at 01:19