DEV Community

Cover image for React Native Performance Optimisation With Hooks
Lakshmeesha
Lakshmeesha

Posted on • Updated on

React Native Performance Optimisation With Hooks

Working Just fine but not that great? 😑.

Its very easy for developers to write working react-native app, but not best performing react-native app. Its been a while, i was finding a way to write a react-native app with maximum performance possible. I was trying all the best practice possible to make app better.
Here are some of my collections of methods, tips & tricks to improve react-native app performance🔥.

1. Stop using inline functions 🌀

First thing, stop using inline function calls right now, react native thinks that the props which has inline function is a new value every-time & it causes unnecessary re-renders in its children components.

Solution

Move all your inline functions to const. (& next step as well )

Example:

Before

After✅


So now app performance is far better?. humm!, not yet, but we are doing some progress. for now we made component much legible.

2. Make proper use of useCallback♻️.

Any of your functions which uses to re-render your component,
which should not cause unnecessary re render, whenever you don't want, whichever the functions used inside jsx elements, bring it out like shown in last step and apply our hero hook useCallback
what will it do?. that is not part of this post anyway, you can find in in many docs & posts. But i will just show how we can implement it to improve react-native performance.

Example


And now we defiantly made some progress by applying our hero hook. This makes sure the FlatList will not re-render because the AwesomeChild is memorised & there is nothing to change its value.
you can observe from above code, empty bracket is used just after our old function wrapping with useCallback, that is dependancy, that is required incase the function is consuming any of other values.

Example


The above code is written to add 1 to its last state, but it always sets 1, because the useCallback memorised the states pressCount as 0 at the first render, whenever we use the state inside useCallback it is always 0, so every time we press, it will be 0+1 = 1. to get the latest values, we need to add states to the empty array inside useCallback. i.e, useCallback(()=>{...},[pressCount])
So its bit of headache to find dependency and fill, i know right!?, for that you just need to configure eslint & eslint-react-hook, after that VS code will take care of it.
Before applying useCallback
Before applying useCallback.
Notice the lag of activating tab.
After applying useCallback
After applying useCallback.

3. memo for Whole component🚦.

use export default React.memo(AwesomeChild) to export almost all of your component, this is very similar to PureComponent from react class turf. it prevents re-rendering of components by comparing prev & next props, sometime it will allow render for some of unwanted prop changes, to level up the restrictions, we can use areEqual function as 2nd argument of the React.memo function,

Example

Unrestricted memo


Restricted memo

In this, component will re-render only if text prop changes from parent component, no re-renders if style prop changes.
(in most of the cases, normal memo will work without any problems)

4. Others tips🔧.

I Hope this post helps some of you guys, i figured it out by spending hours together, thought of sharing which is not easily available on internet.
Comment your thought & tips...

Discussion (7)

Collapse
neiker profile image
Javier Alvarez

Nice article! I just want to point you should avoid unnecessary optimizations. Before using React.memo, useCallback or useMemo is good to measure if it actually cause a performance boost or don't.
"Performance optimizations ALWAYS come with a cost but do NOT always come with a benefit. "
kentcdodds.com/blog/usememo-and-us...

You can also avoid including pressCount on the deps array by using a function on setPressCount like this:
setPressCount(current => current + 1);

Collapse
ltsharma profile image
Lakshmeesha Author

Hey Javier, thanks for the comment 😊 .
I Completely agree with you, "Optimisation always comes with cost". My examples looks very simpler, but the situation i want through (you can see comparison of app working in video i shown), that pushed me to optimising stuffs. We need to choose between Optimisation cost vs Cost of unoptimised app before using them.

Collapse
kylessg profile image
Kyle Johnson • Edited on

Following all of this I'd like to clarify a couple things.

Moving those inline functions up to consts and usecallback will make little to no difference, regardless of usecallback, those functions are still getting redeclared every render which would be the main hit you'd get. The real performance boost here is memoising your child components which is kind of like the old should component update / pure component optimisation.

To prove this I used a tool I made and followed the tutorial, the avg render time for the screen only changed once memoising the child components.

What the graph demonstrates is that if multiple renders are triggered the first mount ofcourse will always take a while, but further re-renders for the entire screen are massively optimised.

Collapse
alebagran profile image
alebagran • Edited on

The after code of the first solution is still wrong, because the functions will still have new references every time the functional component is called, since both awesomeChildListRenderItem and awesomeChildListKeyExtractor will be redeclared.

One option to solve this is to declare the functions outside of the component. But in the case of awesomeChildListRenderItem, it is using setChildState, which can only be accessed from within the component scope. In this particular case only, you can use useCallback instead.

Collapse
alebagran profile image
alebagran

Hey, which perf tool did you use here?

Collapse
meftunca profile image
muhammed burak şentürk

Great !

Collapse
ltsharma profile image
Lakshmeesha Author

Thank you 😊