4

I have read that using an arrow function inline re-creates the function on every component re-render causing performance issues.

In my code I have this situation

render() {
   return (
       <View
          onLayout={(event) => {
             this.itemHeights[index] = event.nativeEvent.layout.height;
          }}  
       >
     ...
   )
 }

I have thought to do something like this to get a better performance:

getItemHeight = (index, {nativeEvent: {layout: {height}}}) => this.itemHeights[index] = event.nativeEvent.layout.height;

render() {
   return (
       <View
          onLayout={(event) => getItemHeight(index, event)}  
       >
     ...
   )
 }

But I am not really sure if this is better... at I have to invoke a function in a inline function. I did it because I need the parameter index, so I can't do:

 <View
    onLayout={getItemHeight}  
 >

I know that this may not be too expensive, but it is very expensive for my use case, as I have to re-render items on the fly.

Any ideas?

1 Answer 1

3

Declaration vs Execution

First of all I think you are confusing two things here. The declaration of a function is something different than the execution of a function.

Also the component does not re render all the time, just because a function is redeclared inside the render functions return.

There is also a vast difference between the performance impact between the declaration of a function and its execution.

Referentially stable function vs inline functions

So what you are doing in your first example is redeclaring a function for the View component. This basically resets the value for the onLayout prop, because inline functions are not referentially stable.

~~In the second example (I figure this is a class component), you are using a referentially stable function, so the prop value of onLayout stays the same.~~

UPDATE: Actually this is not true, my bad. You are still using a instable function. But you could just bring that up as a class member like so:

public getItemHeight(index, {nativeEvent: {layout: {height}}}) { 
  this.itemHeights[index] = event.nativeEvent.layout.height;
}

// ...
// ... inside the render function:
return {
  <View onLayout={this.getItemHeight}></View>
}

But I am not really sure if this is better... at I have to invoke a function in a inline function. I did it because I need the parameter index, so I can't do:

Actually this statement isn't true. You can also retrieve the index with a defined function, as I showed above. Using this code you are just giving the prop a reference to the function that you want to be invoked by the callback. This will populate the arguments just fine.

When do components re render?

Components re render when there is a prop or state change. So in your first example the View component will re render only if the parent component has to be re rendered. So the parent renders and therefore evaluates the it's sub components. This does trigger the render function of the View component and swaps out the function for onLayout.

In your second example (considering my suggested code change above) the View component would not trigger it's render function since the prop value of onLayout did not change.

But that does not mean, that your first example necessarily results in a DOM change and repaint (this is a different algorithm inside React). And the DOM change would be the really expensive part.

Rerender vs Repaint

Rerender is a process that React runs internally. React just triggers the render functions of the component that have to be rerendered. But the repaint inside the actually page during runtime only happens if the resulting DOM is different than before.

You can read more about this in the React Docs: https://reactjs.org/docs/reconciliation.html

So when would you have to use referentially stable functions?

I don't think that you should prematurely optimize such things. It can make the code more bloated and introduce complexity that isn't always necessary.

There is also a whole part on this here: https://reactjs.org/docs/optimizing-performance.html#avoid-reconciliation

If it does not drain your performance, why bother micro optimizing things? Just because you read that inline function are recreated every time (btw. this also applies to non arrow functions. It's the inline declaration that makes it recreate every time) and therefore the render function is triggered every time, doesn't always mean that React has to repaint or that it has a big performance impact.

So never prematurely fiddle around on small performance gains, when there isn't even a problem.

An React based app is a huge beast of code. There will be plenty big picture problems to fix, once you run into performance issues.

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

2 Comments

"Also the component does not re render all the time, just because a function is redeclared inside the render functions return." - I am using the component in a flatlist which remove components that are outside the viewport, I didn't specify this in the question, that is the re-render I talk about, my fault. Anyways, you solve my doubt. Thank you.
The same principles apply for a FlatList. The most expensive operation inside a FlatList is the swapping in and out of UI elements itself. Your function declaration way is basically irrelevant to that.

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.