I recently went down the rabbit hole trying to fix an issue I was having with a seemingly simple react-navigation implementation of a TabNavigator. I followed the docs exactly and didn’t have anything out of the ordinary in my code (or so I thought). The issue was that every time I selected a new tab of the tab navigator, the screen would “jump” as it was rendering.
It looked like this:
It would happen so fast that it didn’t seem like a big deal at first, but as the issue persisted it became an increasing frustration. I couldn’t find or think of anything that would cause this problem, and the GitHub issues page for react-navigation gave me no help either. Part of the issue was also that people would probably use a lot of different nomenclatures to describe the issue, whether it be “jank”, or “jumping” or “stuttering”. But the biggest issue was that I really didn’t understand the problem well enough to even compose a proper search for the solution…
After taking a QuickTime video of the screen jumping, and playing it in slow motion to see what exactly was happening, I noticed that the additional padding above the StatusBar was briefly disappearing during the jump. Interesting. This got me thinking about the usage of React Native’s SafeAreaView since that is what provides the additional padding on the top.
I looked at the official documentation, https://facebook.github.io/react-native/docs/safeareaview but there wasn’t anything interesting there. Searching the react-navigation documentation for “SafeAreaView” yielded this: https://reactnavigation.org/docs/1.x/handling-iphonex/.
👀 This section jumped out at me:
Boom! I stumbled on to the react-native-community page for SafeAreaView, which differs from the primary documentation: https://github.com/react-native-community/react-native-safe-area-view. The react-native-community SafeAreaView does expose the forceInset prop, and documents it as follows:
Sometimes you will observe unexpected behavior and jank because SafeAreaView uses onLayout…
With these changes in place our app looks like it should:
I hope this helps some of my fellow react native developers!