Giter Club home page Giter Club logo

Comments (12)

hanchiang avatar hanchiang commented on June 8, 2024 2

@rwieruch Yeah, I am not quite sure even after reading it.

From facebook:

The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem.

What I understand from this is that creating a callback every time the component renders doesn't suffer from performance hit.

I understood why I needed to bind this - To make this work in the callback function, otherwise it will be undefined.

But the confusion for me was not knowing when I need to bind a method.
So I finally found it here again from facebook:

This is not React-specific behavior; it is a part of how functions work in JavaScript. Generally, if you refer to a method without () after it, such as onClick={this.handleClick}, you should bind that method.

I guess I can use this as a reliable guideline :)

from the-road-to-learn-react.

 avatar commented on June 8, 2024 1

As a beginner, trying to connect all elements together, I was obsessed with the 'binding' and 'context' things. And it confused me. But, unlike I thought, the purpose of the arrow function is not to do a binding there. Like @abuuzayr explained, it prevents the event handler inside the curly braces (onClick={<event handler>}) to get executed on the render() call.
What I missed is the difference between

onClick = {this.handleClick}

that is used in the official documentation, and

onClick = {this.handleClick()}

The first one works because it's not a function call but a reference to the function.
The second, because of the parenthesis, is a function call. And since we need to pass parameters inside the parenthesis

onDismiss(item.objectID)

we have to refer to the function an other way. Using an arrow function. Or defining the function outside the curly braces (but inside the map iteration, to pass the item.objectID parameters).

from the-road-to-learn-react.

 avatar commented on June 8, 2024

I'm confused about the behavior of the handler when fired by the onClick event. In the official documentation in the 'Handling Event' part, we have

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};

    // This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

<button onClick={this.handleClick}> works perfectly here and is not wrapped into another function. Maybe the reason we have to do it in this particular case (Robin tutorial) could be related with the fact that we are in a loop (map.(item => ...)? Which implies that each item has his proper 'context' and we have to bind the onDismiss function to the item context in order to have access to his properties (objectID in this case). And the possible way to bind the handler function to the context is to use an arrow function. Another is to define the function outside the loop (outside the render()). In other words, because of the iteration (map()) we have to do inside the loop the same 'binding' trick that we do in a classical handler. I'm not sure I'm clear ...

from the-road-to-learn-react.

prashantkhurana avatar prashantkhurana commented on June 8, 2024

<button onClick={this.handleClick}> works perfectly here and is not wrapped into another function

this is because of the following :

// This binding is necessary to make `this` work in the callback
    this.handleClick = this.handleClick.bind(this);

Either you do explicit binding (because In JavaScript, class methods are not bound by default.) or you use property initializer syntax or arrow function.

from the-road-to-learn-react.

 avatar commented on June 8, 2024

You're perfectly right. The point is since the binding is made in the constructor for the inDismiss method

constructor(props) {
super(props);
this.state = {
list,
};
this.onDismiss = this.onDismiss.bind(this);
}

why do we have to bind it again inside the render ?

<button
onClick={() => onDismiss(item.objectID)}
type="button"
>

It's not necessary in the React example above. My hypothesis is that since we are iterating a list of objects (the news), each <button/> need to be bind with the context of his own item in order to access the properties (item.objectId).

render() {
  const { list, pattern, onDismiss } = this.props;
  return (
    <div>
      { list.filter(isSearched(pattern)).map(item =>
        <div key={item.objectID}>
        ...
         <button
           onClick={() => onDismiss(item.objectID)}
           type="button"
         >
         Dismiss
         </button>
       </div>
      )}
    </div>
  );
}

from the-road-to-learn-react.

 avatar commented on June 8, 2024

In the React's doc (last paragraph) they encourage us avoiding the use of an arrow function as a callback for an event:

The problem with this syntax is that a different callback is created each time the LoggingButton renders. In most cases, this is fine. However, if this callback is passed as a prop to lower components, those components might do an extra re-rendering. We generally recommend binding in the constructor or using the property initializer syntax, to avoid this sort of performance problem.

But here it is precisely the behavior we want for our list of news: create a different callback for each button associated with his own new thanks to the item.objectID parameter.

from the-road-to-learn-react.

prashantkhurana avatar prashantkhurana commented on June 8, 2024

ahh , my bad. I misunderstood what you were saying.

I don't think we need to bind in this particular case(code on page 33). We are already using an arrow function, so no need to bind.

From what I understand, arrow functions do have a performance overhead as you mentioned. One solution is to create a separate component which is what we do by the end of chapter 2.

from the-road-to-learn-react.

rwieruch avatar rwieruch commented on June 8, 2024

Totally right! Sorry for stepping in too late here. But I guess after struggling with the problem on your own, you really have internalized how it works now ๐Ÿ‘

In the React's doc (last paragraph) they encourage us avoiding the use of an arrow function as a callback for an event:

That's right. It is not encouraged in the first place and there are ways around it. In the end, it is hard to keep the balance of keeping it simple for newcomers and teaching best practices from the beginning that would add complexity to the whole thing. But maybe it is something that could be refactored in an advanced chapter?

Thanks for all your input! I will definitely update this part in the next edition of the book, because I saw several people run into the issue while reading the book but also in personal workshops.

from the-road-to-learn-react.

 avatar commented on June 8, 2024

Thanks! And bravo for your book: it's a very pleasant and stimulating road to learn React! ๐Ÿ‘

from the-road-to-learn-react.

hanchiang avatar hanchiang commented on June 8, 2024

I also spent some time trying to understand different ways of passing arguments to an event handler. Using the ES6 arrow function makes it easy, but might have performance overheads.

One way is to use a sub component to achieve this. The main component will pass the argument and event handler to the child, and the child will simply call the handler with the argument, as seen here: https://stackoverflow.com/a/29810951

Another way mentioned is to curry the event handler with with the argument, then return another function containing the event object, as seen here: https://stackoverflow.com/a/45448802

For the first method, the flow of data is clear, however it takes more code/
For the second method, code is short and sweet, however it may not optimised?

What do you think?

from the-road-to-learn-react.

rwieruch avatar rwieruch commented on June 8, 2024

@hanchiang great additions, I will add these in the next edition.

Recently I heard more people arguing about the performance impacts of using inline arrow functions. But if you are not using these in dozens of components, the performance impact should be small. Nevertheless, it is great to teach people the best practices in the end. Thanks again everyone for your contribution.

from the-road-to-learn-react.

rwieruch avatar rwieruch commented on June 8, 2024
  • Chapter about Bindings and Explanation about Arrow Function in Event Handler 69b2a46
  • added performance implications b5bb077

from the-road-to-learn-react.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.