software-mansion/react-native-screens

enableFreeze does not work on Web (react-native-web)

hbomatt opened this issue ยท 5 comments

Description

I'm using React-Navigation v6 along with the latest version of react-native-screens and have followed the react-freeze Quick Start Guide for React-Navigation... but how can I tell that it's actually doing anything? enableFreeze(true); seems to have zero effect on the app that I'm working on. I've just been testing on Web (react-native-web) initially...

  • I don't see any Freeze components in the component hierarchy using React Developer Tools in Chrome, running on Web via react-native-web.
  • I don't see any new Suspense-related components after enabling react-freeze.
  • react-native-screens doesn't seem to provide a freezeEnabled() method, like screensEnabled()...
  • I haven't noticed any change in performance when doing tasks like resizing the browser window with a navigation backstack of 10+ screens.

Stepping into the enableFreeze call, I see:

export function enableFreeze(shouldEnableReactFreeze = true) {// noop
}

export function enableFreeze(shouldEnableReactFreeze = true): void {

I was surprised to see that the react-freeze integration isn't compatible with react-native-web apps that use react-native-screens.

Is this a bug or by design?

Screenshots

Steps To Reproduce

  1. Call enableFreeze(true); during app startup.
  2. Navigate around to add a dozen screen instances to your backstack.
  3. Resize browser window.

Expected behavior

Only the current screen and the previous screen re-render, the other screen instances in the backstack do not re-render.

Actual behavior

Every screen in the backstack re-renders, causing a severe performance hit (several seconds to re-render after browser window resizing on a MBP)

Reproduction

I don't believe a Snack repro is needed, the issue is clear when looking at the react-native-screens source code for the enableFreeze method - comparing index.tsx (no-op) to index.native.tsx (actually enables react-freeze)

Platform

  • iOS
  • Android
  • Web
  • Windows
  • tvOS

Workflow

  • Managed workflow
  • Bare workflow

Package versions

package version
react-native 0.67.2
@react-navigation/native 6.0.8
@react-navigation/native-stack n/a
react-native-screens 3.13.1
react-native-safe-area-context 3.1.9
react-native-gesture-handler 1.10.3
react-native-reanimated 1.13.2
expo n/a

Hello @hbomatt ๐Ÿ‘‹

Yes, all of your observations are correct and it's neither a bug nor by design. We just haven't managed to add react-freeze support for react-native-web yet. This is something we'll look into in the future. But I won't provide any estimations tho. Sorry!

Cheers

Hi @kacperkapusciak ๐Ÿ‘‹๐Ÿป

Thanks for the explanation! I totally understand, react-freeze was released so recently I was surprised to even see the slick integration with react-native-screens from the get-go. I'm extremely excited for the react-freeze project's potential to help fix performance issues in an app with lots of complex screens & navigation backstacks that typically contain a lot of screen instances. For now, we'll start using it on Android, iOS, and potentially a few additional platforms. ๐Ÿ‘๐Ÿป

๐Ÿคž๐Ÿป that we'll eventually be able to use it on Web as well ๐Ÿ˜„

Thank you for your (and the entire team's) contributions to react-native-screens, react-freeze, etc. ๐Ÿš€ ๐Ÿš€ ๐Ÿš€

Just for other devs that come across this issue, I ended up relying on react-native-screens to handle freezing & thawing screens for native in an app built with react-navigation and it's working very well. To improve performance in the same app on Web, I opted to create a react-native component that handles the freezing & thawing logic by examining navigation state and toggling the <Freeze /> component's prop, as appropriate. If react-native-screens adds support for Web in the future, there would be benefits to switch to using it instead - but in the meanwhile, you can definitely work around this and successfully use react-freeze in your app on Web. Thanks!

hello @hbomatt
I looked at your changes, but it would destroy the useIsFocused of bottom-tabs.

hello @hbomatt I looked at your changes, but it would destroy the useIsFocused of bottom-tabs.

Thanks, that was a non-issue for us because we don't use a tabbed interface on Web, we do use a tabbed interface on iOS/Android/FireTV/etc. but that uses the native freeze support instead. I just used the custom freeze tweak specifically on Web in the non-tabbed UI. It was a product/design choice to have the tabbed UI on mobile and a non-tabbed UI on Web. I guess that saved us from encountering the problem you discovered ๐Ÿ˜… Thanks!

The biggest pain with this custom freeze approach on Web was disabling the various hooks that would execute on pages in the backstack, for perf reasons, but that was a pretty straight-forward fix once we realized what was going on.