Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevented inactive tabs from rendering #650

Merged
merged 14 commits into from
Oct 20, 2022
Merged

Prevented inactive tabs from rendering #650

merged 14 commits into from
Oct 20, 2022

Conversation

grahammendick
Copy link
Owner

This work was triggered by the Lazy Initialized TabBar discussion.

Used the same technique from #547 to freeze inactive tabs. By default, the Navigation router only freezes a tab once it’s been visited. There’s no way for the Navigation router to know when it’s safe to freeze a tab before it’s been visited.

The typical way is to wait to render the tab until it’s pressed. But this isn’t good because most tabs need to fetch data. Freezing before the fetch starts means that the tab will be in a loading state when activated. It’s better to freeze once the fetch has begun so that it’s completed by the time the tab is activated. This avoids a loading state because it only has to render the already fetched data when it’s unfrozen.

So moved the decision about when to freeze an unvisited tab into userland. Created a TabBarItemContext with an onLoad function. The user calls onLoad once it’s safe to freeze. In a Twitter example, the user freezes the notifications tab once the data is fetched,

const NotificationsTab = () => {
  const {onLoad} = useContext(TabBarItemContext);
  const [notifications, setNotifications] = useState();
  useEffect(() => {
    onLoad();
    const data = await fetch();
    setNotifications(data);
  }, [])
}

Also added this change to Navigation React Native Web. Added a lazy prop so the tab can be frozen immediately. Couldn’t add the lazy prop on Native because it can cause a blank flash . The tab press happens first in native and the tab goes blank while it waits for the first render to complete in JavaScript.

Plan to freeze loaded and inactive tabs. Decision of when a tab is first loaded is up to developer. Once a tab is selected it is considered loaded. A loaded tab can't be marked as unloaded. It's just about whether allowed to freeze - if a tab's been seen by user then can definitely freeze
Applied trick to prevent tab from having display set to false - React Native sets suspended items to display false, but that breaks lots of things on native side
On android, can swipe tabs to left or right. Safest not to freeze these so don't get a flicker of old content when swiping either way. Mind you, similar scenario on ios with swipe back to frozen scene. But solve that by listening to peek and unfreezing. Don't want to do that yet because that would need a render when swiping. For now will just not freeze them
The freezable prop already checks not selected
No need to check selected explicitly because it's just distance 0
Select Notifications tab in Twitter sample and then go back on Android. It wouldn't do anything because the back press on the Home tab thought it was selected - it had a stale closure. So moved the back press outside of the freeze so the onPress has the latest data
Brings in line with native equivalent and prepares for suspend/freeze
Copied over freeze and TabBarItemContext so can use them in native web
Match native web public surface to native
This prop doesn't exist on native, see #634 (reply in thread). In summary, tabs are rendered async so delaying first render could cause a flash of empty content. On web don't have this problem so safe to have lazy first render
@grahammendick grahammendick merged commit 83b118b into master Oct 20, 2022
@grahammendick grahammendick deleted the tabs-freeze branch October 20, 2022 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant