From 75c15c1facbae598b463477d7d0e3cebd2aacdc6 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Wed, 25 Sep 2024 16:56:50 +0200 Subject: [PATCH] feat: add basic React Server Component support (#2170) ## Description Add basic support for React Server Components support. Related PRs for more context: - https://github.com/necolas/react-native-web/pull/2678 - https://github.com/th3rdwave/react-native-safe-area-context/pull/502 - https://github.com/software-mansion/react-native-svg/pull/2287 ## Changes - Added basic React Server Component support ## Test code and steps to reproduce - It's kinda hard to test this E2E. I wrote a small jest runner in jest-expo which executes in RSC mode, but it requires React 19 to work. Here's where I tested this patch https://github.com/expo/expo/pull/29404 - It will likely break between now and the full release, but this should at least reduce the number of patches required to work on Expo Router support. - There's pretty good compilation on web: ``` 2:I["../../node_modules/react-native-web/dist/exports/View/index.js",[],""] 3:I["../../node_modules/react-native-web/dist/exports/Image/index.js",[],""] 1:{"name":"ScreenStackHeaderBackButtonImage","env":"Server","owner":null} 0:D"$1" 0:["$","$L2",null,{"children":["$","$L3",null,{"resizeMode":"center","fadeDuration":0},"$1"]},"$1"] ``` - And more opaque compilation on native platforms: ``` 1:I["../../node_modules/react-native-screens/src/components/ScreenStackHeaderConfig.tsx",[],"ScreenStackHeaderBackButtonImage"] 0:["$","$L1",null,{},null] ``` ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes --- src/TransitionProgressContext.tsx | 2 ++ src/components/Screen.tsx | 2 ++ src/components/Screen.web.tsx | 3 +++ src/components/ScreenContainer.tsx | 2 ++ src/components/ScreenStack.tsx | 2 ++ src/components/ScreenStackHeaderConfig.tsx | 2 ++ src/components/SearchBar.tsx | 2 ++ src/core.ts | 2 ++ src/fabric/FullWindowOverlayNativeComponent.ts | 2 ++ src/fabric/ModalScreenNativeComponent.ts | 2 ++ src/fabric/NativeScreensModule.ts | 2 ++ src/fabric/ScreenContainerNativeComponent.ts | 2 ++ src/fabric/ScreenNativeComponent.ts | 2 ++ src/fabric/ScreenNavigationContainerNativeComponent.ts | 2 ++ src/fabric/ScreenStackHeaderConfigNativeComponent.ts | 2 ++ src/fabric/ScreenStackHeaderSubviewNativeComponent.ts | 2 ++ src/fabric/ScreenStackNativeComponent.ts | 2 ++ src/fabric/SearchBarNativeComponent.ts | 2 ++ src/native-stack/contexts/GHContext.tsx | 2 ++ 19 files changed, 39 insertions(+) diff --git a/src/TransitionProgressContext.tsx b/src/TransitionProgressContext.tsx index 30cfd6a94f..6382473fbc 100644 --- a/src/TransitionProgressContext.tsx +++ b/src/TransitionProgressContext.tsx @@ -1,3 +1,5 @@ +'use client'; + import * as React from 'react'; import { Animated } from 'react-native'; diff --git a/src/components/Screen.tsx b/src/components/Screen.tsx index 122a9042b2..b553763834 100644 --- a/src/components/Screen.tsx +++ b/src/components/Screen.tsx @@ -1,3 +1,5 @@ +'use client'; + import React from 'react'; import { Animated, View, Platform } from 'react-native'; diff --git a/src/components/Screen.web.tsx b/src/components/Screen.web.tsx index c624a49eaf..183b6f8512 100644 --- a/src/components/Screen.web.tsx +++ b/src/components/Screen.web.tsx @@ -1,3 +1,5 @@ +'use client'; + import { ScreenProps } from 'react-native-screens'; import { Animated, View } from 'react-native'; import React from 'react'; @@ -8,6 +10,7 @@ export const InnerScreen = View; // We're using class component here because of the error from reanimated: // createAnimatedComponent` does not support stateless functional components; use a class component instead. +// NOTE: React Server Components do not support class components. export class NativeScreen extends React.Component { render(): JSX.Element { let { diff --git a/src/components/ScreenContainer.tsx b/src/components/ScreenContainer.tsx index 1a968b2e8a..65c907a1f6 100644 --- a/src/components/ScreenContainer.tsx +++ b/src/components/ScreenContainer.tsx @@ -1,3 +1,5 @@ +'use client'; + import { Platform, View } from 'react-native'; import React from 'react'; import { ScreenContainerProps } from 'react-native-screens'; diff --git a/src/components/ScreenStack.tsx b/src/components/ScreenStack.tsx index 46043b6359..310b6a6938 100644 --- a/src/components/ScreenStack.tsx +++ b/src/components/ScreenStack.tsx @@ -1,3 +1,5 @@ +'use client'; + import React from 'react'; import { ScreenStackProps, freezeEnabled } from 'react-native-screens'; import DelayedFreeze from './helpers/DelayedFreeze'; diff --git a/src/components/ScreenStackHeaderConfig.tsx b/src/components/ScreenStackHeaderConfig.tsx index e65799092b..f3339fa5bd 100644 --- a/src/components/ScreenStackHeaderConfig.tsx +++ b/src/components/ScreenStackHeaderConfig.tsx @@ -1,3 +1,5 @@ +'use client'; + import React from 'react'; import { HeaderSubviewTypes, diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 981f67dc00..0874531679 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -1,3 +1,5 @@ +'use client'; + import React from 'react'; import { isSearchBarAvailableForCurrentPlatform, diff --git a/src/core.ts b/src/core.ts index 7a5f3971bc..0a28fdf9e7 100644 --- a/src/core.ts +++ b/src/core.ts @@ -1,3 +1,5 @@ +'use client'; + import { Platform, UIManager } from 'react-native'; // const that tells if the library should use new implementation, will be undefined for older versions diff --git a/src/fabric/FullWindowOverlayNativeComponent.ts b/src/fabric/FullWindowOverlayNativeComponent.ts index 9d1c662e16..dcbd10d259 100644 --- a/src/fabric/FullWindowOverlayNativeComponent.ts +++ b/src/fabric/FullWindowOverlayNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; diff --git a/src/fabric/ModalScreenNativeComponent.ts b/src/fabric/ModalScreenNativeComponent.ts index ab8a5e889d..979dddeeeb 100644 --- a/src/fabric/ModalScreenNativeComponent.ts +++ b/src/fabric/ModalScreenNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps, ColorValue } from 'react-native'; import type { diff --git a/src/fabric/NativeScreensModule.ts b/src/fabric/NativeScreensModule.ts index 23c2bc767c..bc334ff35f 100644 --- a/src/fabric/NativeScreensModule.ts +++ b/src/fabric/NativeScreensModule.ts @@ -1,3 +1,5 @@ +'use client'; + /* eslint-disable @typescript-eslint/ban-types */ import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; diff --git a/src/fabric/ScreenContainerNativeComponent.ts b/src/fabric/ScreenContainerNativeComponent.ts index 290375c6d5..b8f0c7b250 100644 --- a/src/fabric/ScreenContainerNativeComponent.ts +++ b/src/fabric/ScreenContainerNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; diff --git a/src/fabric/ScreenNativeComponent.ts b/src/fabric/ScreenNativeComponent.ts index d552cd6bb4..bf7242cfd5 100644 --- a/src/fabric/ScreenNativeComponent.ts +++ b/src/fabric/ScreenNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps, ColorValue } from 'react-native'; import type { diff --git a/src/fabric/ScreenNavigationContainerNativeComponent.ts b/src/fabric/ScreenNavigationContainerNativeComponent.ts index 89fb72f164..906ae64047 100644 --- a/src/fabric/ScreenNavigationContainerNativeComponent.ts +++ b/src/fabric/ScreenNavigationContainerNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; diff --git a/src/fabric/ScreenStackHeaderConfigNativeComponent.ts b/src/fabric/ScreenStackHeaderConfigNativeComponent.ts index de0574aa1b..9bf6634e24 100644 --- a/src/fabric/ScreenStackHeaderConfigNativeComponent.ts +++ b/src/fabric/ScreenStackHeaderConfigNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps, ColorValue } from 'react-native'; import type { diff --git a/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts b/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts index 625e578459..189702dc13 100644 --- a/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts +++ b/src/fabric/ScreenStackHeaderSubviewNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; import type { WithDefault } from 'react-native/Libraries/Types/CodegenTypes'; diff --git a/src/fabric/ScreenStackNativeComponent.ts b/src/fabric/ScreenStackNativeComponent.ts index fbf56654ec..3400cfe099 100644 --- a/src/fabric/ScreenStackNativeComponent.ts +++ b/src/fabric/ScreenStackNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps } from 'react-native'; import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; diff --git a/src/fabric/SearchBarNativeComponent.ts b/src/fabric/SearchBarNativeComponent.ts index c10dc70e44..467442aa2a 100644 --- a/src/fabric/SearchBarNativeComponent.ts +++ b/src/fabric/SearchBarNativeComponent.ts @@ -1,3 +1,5 @@ +'use client'; + /* eslint-disable */ import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; import type { ViewProps, ColorValue, HostComponent } from 'react-native'; diff --git a/src/native-stack/contexts/GHContext.tsx b/src/native-stack/contexts/GHContext.tsx index 6b8b29096b..3e2a5cdd07 100644 --- a/src/native-stack/contexts/GHContext.tsx +++ b/src/native-stack/contexts/GHContext.tsx @@ -1,3 +1,5 @@ +'use client'; + import React, { PropsWithChildren } from 'react'; import { GestureProviderProps } from '../types';