software-mansion / react-native-screens

Native navigation primitives for your React Native app.
https://docs.swmansion.com/react-native-screens/
MIT License
3.08k stars 519 forks source link

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

Closed hbomatt closed 2 years ago

hbomatt commented 2 years ago

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...

Stepping into the enableFreeze call, I see:

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

https://github.com/software-mansion/react-native-screens/blob/bef0d67669f24536e3c112940bb6fefcaca6bfbb/src/index.tsx#L31

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

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
kacperkapusciak commented 2 years ago

Hello @hbomatt :wave:

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

hbomatt commented 2 years ago

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. 🚀 🚀 🚀

hbomatt commented 2 years ago

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!

QuincySx commented 1 year ago

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

hbomatt commented 1 year ago

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.