2

My question is to do with the issue react has where you should not bind a function within the render function, as this will cause a new instance of that function to be created for each render, eventually causing the browser to run out of memory and crash.

Based on the answers I got to this question:

Create function that can pass a parameter without making a new component

It seems that if you want to pass a parameter into a function, you either have to make a new component, or essentially bind in the render function using the arrow function ()=>

Given this, there is a trade off between creating many components to do this, or accepting that you will sometimes have to bind in the render function.

In order to determine which option to take, I assume you would have to estimate the effect of binding in the render function.

So I am trying to understand exactly what will happen to browser memory with too many binds in the render function.

So my question(s) are as follows:

Am I correct in assuming that any memory used up by binding will be freed when a user refreshes the page (eg presses F5 in Chrome)? If not, when will the memory be freed up?

Then, given react applications are single page apps, the user may never actually refresh the page - they may think they are changing page, but in fact they are always on the same page. If this is the case, is there any other point where memory will be freed up - eg if they user navigates to a different page within the react app, will it free up the memory? The reason I ask is because if react never frees up memory int his way, then wouldn't all react apps eventually crash for this reason, unless a user refreshed their page?

Alex
  • 3,730
  • 9
  • 43
  • 94
  • Also check this answer on how to avoid binding a function in render https://stackoverflow.com/questions/45053622/how-to-avoid-binding-inside-render-method/45053753#45053753 – Shubham Khatri Sep 28 '17 at 08:26
  • why not use smth like: {this.someFunc(param)}/>? (If I understood you correclty) – Giorgi Moniava Sep 28 '17 at 08:45
  • @GiorgiMoniava that wills till cause the same issue, as your ()=> function is essentailly binding a new function – Alex Sep 28 '17 at 09:11
  • @ShubhamKhatri Your solution will only work if you are not passing any parameters into the function – Alex Sep 28 '17 at 09:12
  • No it will work even if you want to pass parameters to the function, thats what the solution was for, otherwise you could just directly call this.someFunc – Shubham Khatri Sep 28 '17 at 09:15
  • @ShubhamKhatri my apologies, I failed to read the answer properly. However, I did also mention this solution, but the issue is that this may force me to make a large number of components. I am trying to understand the impact on memory of the bind issue, so I can decide when to use a component, and when to allow the bind in render – Alex Sep 28 '17 at 09:31
  • thats the reason I did not mark it as a duplicate. however the answer contains another solution that does prevent duplication to some extent using memoization – Shubham Khatri Sep 28 '17 at 09:32

1 Answers1

1

You are misinterpreting what an arrow function's context actually is. It has none. It gets the this that it uses from lexical scoping (the scope above it). Arrow functions are not 'auto-binded'. You do not make a new instance when you use an arrow function and they are in the proper scope by default.

But using a normal function and bind is a perfectly valid way of doing this.

Performance-wise, using bind in your render function matters an incredible amount less than you make it out to be. That being said, the recommended way to circumvent this is to pre-bind the functions in your constructor. You will create one instance of the function upon mounting, and never again after that (for the life of the component).

constructor(props) {
    super(props)
    this.state = {}
    this.myFunc = this.myFunc.bind(this)
}

The problem described in the link you showed does not exist, regarding argument passing inside the event handler. The OP is using call for no reason.

<button onClick={(e) => this.myFunc.call(this, e)></button>

call is not neccesary at all. After using bind in your constructor, it just has to look like this:

<button onClick={(e) => this.myFunc(e)></button>

Note that this syntax actually doesn't require you to use bind in your constructor, because it's an arrow function. But for continuity's sake, if you're going to bind all of your methods in your constructor, you might as well to prevent any confusion on your end.

Andrew
  • 7,201
  • 5
  • 25
  • 34
  • surely the syntax () => {} is a way of declaring a new funciton on the fly eg each time you write this code, you are creating a new function? In which case every time this appears in your render you are creating a new function? – Alex Sep 28 '17 at 12:41
  • also please note that your answer in no way answers my question, it answers a different question altogether. I am asking about browser memory being freed up when using react – Alex Sep 28 '17 at 12:46
  • @Alex I see that it doesn't answer it now. I only talk about everything leading up to the question itself. Remember that event listener functions are callbacks. Even using `onClick={this.myFunc}` is a callback. You just aren't explicitly stating it. So the difference between arrow function and `bind` is that arrow functions creates a callback function, as opposed to bind, that makes a callback function _and_ a new instance of the function – Andrew Sep 28 '17 at 18:21