简体   繁体   中英

Passing functions to components in React

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?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM