I am new to react native and I trying to optimize performance.
My Touch events are very slow and I was going through RN documentation on performance and they have mentioned to use requestAnimationFrame
with this example
handleOnPress() {
// Always use TimerMixin with requestAnimationFrame, setTimeout and
// setInterval
this.requestAnimationFrame(() => {
this.doExpensiveAction();
});
}
Now, this description sounds very vague and hard for me to comprehend its usage
Like, I have this touchable event in my RN app
<TouchableWithoutFeedback onPress={() => this.touched(this.props.coinShortName)}>
Which calls this method
touched = (id) => {
this.setState({selectedPostId: id})
if (this.props.coinShortName == this.state.selectedPostId ) {
this.setState({stateToDisplay: !this.state.stateToDisplay})
}
}
Question: Can someone please tell me on how I need to/should use it in my app?
As mentioned , you need to wrap your expensive action in an instance of
requestAnimationFrame
.Usage
I'm going to convert my comment into an answer, so I can format it better and hopefully help someone in the future too. I don't expressly recommend marking my answer as correct, but I think this answer should be here alongside this question.
This article here should give you some backstory on
requestAnimationFrame
: http://www.javascriptkit.com/javatutors/requestanimationframe.shtml.I would recommend reading the article I linked above and then read my answer after.
I will just explicitly mention that
requestAnimationFrame
could appear similar tosetTimeout(() => {}, 0)
, but if you had a Zack Morris phone made in 1985, its "as soon as possible" might be 5 seconds later, thus making your animation look terrible, similar to when your character lags across the screen in a video game. The function may have been called at the correct time, but it did not actually execute at the correct time.It can be helpful to imagine a collection phase and a rendering phase. I'm sorry, I don't know the exact terms for this stuff, but human eyes see smooth movement at I think 20 FPS, but what that means is you have 20 "frames", so it's like calculating something 20 times. It's like collecting a bunch of kids and pushing them into a bus 20 times per second. Pushing them into the bus is an event, and it's analogous to repainting your screen. Sometimes kids can get left behind and extra kids picked up next time, so you can imagine the gains to perceived smoothness of flow over time.
It's important to note that optimizations are being made with respect to the next repaint, or the next time the screen 'changes'.
requestAnimationFrame
does work under the hood to ensure the animation occurs at the correct time and is smooth, meaning the pixels were where they were supposed to be at the right time. (I think you would derive a lot of meaning if you checked out the definitions for "what is a janky animation", and look at some of the discussion around that. I mention that because we want to understand more about the repainting process and what kinds of things are important and why)I recall that
requestAnimationFrame
can ditch calculations that would occur too late. For example, if you click the button and a pixel goes from 0% to 25% to 50% to 75% to 100% (some arbitrary distance calculation). We could say that after 1 second, the pixel should have travelled 50% of the distance and after 2 seconds, it should be at 100%, the final resting place.It's more important that the pixels are in the correct place at the correct time than it is for them to travel to exactly every place they were supposed to.
requestAnimationFrame
is helping you do this. If the screen is about to repaint, and "it" needs to run a calculation that would take too long, "it" just ignores it and skips to the next frame. It's like trimming fat to keep on pace and therefore, avoid jank.requestAnimationFrame
is a solution for the same challenges whether it's in your web browser or iOS or Android. They all do this process of painting the screen over and over again. You could start calculating something needed for the next repaint but start too late so it's not done when the next repaint occurs.Imagine your animation was smooth but your phone received 20 push notifications all of a sudden that bogged down the CPU, causing your animation to be delayed by
16.7 milliseconds
. Rather than display the pixel at the correct place at the wrong time,requestAnimationFrame
helps by making the pixel be in the correct place at the correct time, but it may do some magic and not even try to paint the pixel sometimes when it would have otherwise, thus saving performance and increasing perceived smoothness.I just realized this is a wall of text, but I think it will be informational.
These repaints occur about 60 frames per second, so
requestAnimationFrame
could fire like 60 times a second when it calculates is the most optimal time. There are 1000 milliseconds in 1 second, so 60 FPS is one frame every16.7ms
. If the human eye perceives smoothness at 20FPS, then it means you could in theory repaint every 45ms or 30% as much, and the animation would still be smooth.My definitions may be inaccurate, but I hope they can help give you a sense what is happening.
it would be event better if you removed the useless
id
parameter in thetouched
function by using directlythis.props.coinShortName
inside so you could writeAnyway, the
touched
function doesn't seem to be really expensive so I don't know if it will solve your performance issue