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

fix: wrap Screen with ScreenContext #1539

Merged
merged 3 commits into from
Jul 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions FabricTestExample/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import React from 'react';

import {enableFreeze} from 'react-native-screens';
import {ReanimatedScreenProvider} from 'react-native-screens/reanimated';

import Test42 from './src/Test42';
import Test111 from './src/Test111';
Expand Down Expand Up @@ -84,9 +83,5 @@ import Test1476 from './src/Test1476';
enableFreeze(true);

export default function App() {
return (
<ReanimatedScreenProvider>
<Test42 />
</ReanimatedScreenProvider>
);
return <Test42 />;
}
49 changes: 27 additions & 22 deletions FabricTestExample/src/Test887.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import {
NativeStackNavigationProp,
} from 'react-native-screens/native-stack';
import {useTransitionProgress} from 'react-native-screens';
import {useReanimatedTransitionProgress} from 'react-native-screens/reanimated';
import {
useReanimatedTransitionProgress,
ReanimatedScreenProvider,
} from 'react-native-screens/reanimated';
import Animated, {
useAnimatedStyle,
useDerivedValue,
} from 'react-native-reanimated';
import { createStackNavigator } from '@react-navigation/stack';
import {createStackNavigator} from '@react-navigation/stack';

const Stack = createNativeStackNavigator();

Expand All @@ -30,9 +33,9 @@ const NestedStack = createStackNavigator();
function NestedFirst() {
return (
<NestedStack.Navigator>
<NestedStack.Screen name="NestedFirst" component={First}/>
<NestedStack.Screen name="NestedFirst" component={First} />
</NestedStack.Navigator>
)
);
}

type SimpleStackParams = {
Expand All @@ -42,23 +45,25 @@ type SimpleStackParams = {
};
export default function App(): JSX.Element {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
stackAnimation: 'fade_from_bottom',
headerShown: true,
customAnimationOnSwipe: true,
// stackPresentation: 'transparentModal',
}}>
<Stack.Screen name="First" component={NestedFirst} />
<Stack.Screen name="Second" component={Second} />
<Stack.Screen
name="Third"
component={Dialog}
options={{stackPresentation: 'modal'}}
/>
</Stack.Navigator>
</NavigationContainer>
<ReanimatedScreenProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
stackAnimation: 'fade_from_bottom',
headerShown: true,
customAnimationOnSwipe: true,
// stackPresentation: 'transparentModal',
}}>
<Stack.Screen name="First" component={NestedFirst} />
<Stack.Screen name="Second" component={Second} />
<Stack.Screen
name="Third"
component={Dialog}
options={{stackPresentation: 'modal'}}
/>
</Stack.Navigator>
</NavigationContainer>
</ReanimatedScreenProvider>
);
}

Expand Down Expand Up @@ -88,7 +93,7 @@ function SiblingView() {
});

return (
<>
<>
<Animated.View style={reaStyle} />
<RNAnimated.View
style={{opacity, height: 50, width: '100%', backgroundColor: 'green'}}
Expand Down
8 changes: 2 additions & 6 deletions TestsExample/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import React from 'react';

import {enableFreeze} from 'react-native-screens';
import {ReanimatedScreenProvider} from 'react-native-screens/reanimated';

import Test42 from './src/Test42';
import Test111 from './src/Test111';
Expand Down Expand Up @@ -81,13 +80,10 @@ import Test1419 from './src/Test1419';
import Test1473 from './src/Test1473';
import Test1476 from './src/Test1476';
import Test1509 from './src/Test1509';
import Test1539 from './src/Test1539';

enableFreeze(true);

export default function App() {
return (
<ReanimatedScreenProvider>
<Test42 />
</ReanimatedScreenProvider>
);
return <Test42 />;
}
58 changes: 58 additions & 0 deletions TestsExample/src/Test1539.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import {NavigationContainer, useNavigation} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import * as React from 'react';
import {
ReanimatedScreenProvider,
useReanimatedTransitionProgress,
} from 'react-native-screens/reanimated';
import Reanimated, {
useAnimatedStyle,
useDerivedValue,
} from 'react-native-reanimated';
import {Button} from 'react-native';

export default function App() {
return (
<ReanimatedScreenProvider>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Root" component={RootScreen} />
<Stack.Screen name="Second" component={SecondScreen} />
</Stack.Navigator>
</NavigationContainer>
</ReanimatedScreenProvider>
);
}

const Stack = createNativeStackNavigator();

function RootScreen() {
const {navigate} = useNavigation();
const reaProgress = useReanimatedTransitionProgress();
const sv = useDerivedValue(
() =>
(reaProgress.progress.value < 0.5
? reaProgress.progress.value * 50
: (1 - reaProgress.progress.value) * 50) + 50,
);
const reaStyle = useAnimatedStyle(() => {
return {
width: sv.value,
height: sv.value,
backgroundColor: 'blue',
};
});

return (
<>
<Reanimated.View style={reaStyle} />
<Button
title="Navigate to second screen"
onPress={() => navigate('Second')}
/>
</>
);
}
function SecondScreen() {
return <></>;
}
45 changes: 25 additions & 20 deletions TestsExample/src/Test887.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import {
NativeStackNavigationProp,
} from 'react-native-screens/native-stack';
import {useTransitionProgress} from 'react-native-screens';
import {useReanimatedTransitionProgress} from 'react-native-screens/reanimated';
import {
useReanimatedTransitionProgress,
ReanimatedScreenProvider,
} from 'react-native-screens/reanimated';
import Animated, {
useAnimatedStyle,
useDerivedValue,
} from 'react-native-reanimated';
import { createStackNavigator } from '@react-navigation/stack';
import {createStackNavigator} from '@react-navigation/stack';

const Stack = createNativeStackNavigator();

Expand All @@ -30,9 +33,9 @@ const NestedStack = createStackNavigator();
function NestedFirst() {
return (
<NestedStack.Navigator>
<NestedStack.Screen name="NestedFirst" component={First}/>
<NestedStack.Screen name="NestedFirst" component={First} />
</NestedStack.Navigator>
)
);
}

type SimpleStackParams = {
Expand All @@ -42,21 +45,23 @@ type SimpleStackParams = {
};
export default function App(): JSX.Element {
return (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
stackAnimation: 'fade_from_bottom',
// stackPresentation: 'transparentModal',
}}>
<Stack.Screen name="First" component={NestedFirst} />
<Stack.Screen name="Second" component={Second} />
<Stack.Screen
name="Third"
component={Dialog}
options={{stackPresentation: 'modal'}}
/>
</Stack.Navigator>
</NavigationContainer>
<ReanimatedScreenProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
stackAnimation: 'fade_from_bottom',
// stackPresentation: 'transparentModal',
}}>
<Stack.Screen name="First" component={NestedFirst} />
<Stack.Screen name="Second" component={Second} />
<Stack.Screen
name="Third"
component={Dialog}
options={{stackPresentation: 'modal'}}
/>
</Stack.Navigator>
</NavigationContainer>
</ReanimatedScreenProvider>
);
}

Expand Down Expand Up @@ -86,7 +91,7 @@ function SiblingView() {
});

return (
<>
<>
<Animated.View style={reaStyle} />
<RNAnimated.View
style={{opacity, height: 50, width: '100%', backgroundColor: 'green'}}
Expand Down
16 changes: 13 additions & 3 deletions src/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ interface ViewConfig extends View {
};
}

class Screen extends React.Component<ScreenProps> {
class InnerScreen extends React.Component<ScreenProps> {
private ref: React.ElementRef<typeof View> | null = null;
private closing = new Animated.Value(0);
private progress = new Animated.Value(0);
Expand Down Expand Up @@ -408,8 +408,17 @@ export type {
};

// context to be used when the user wants to use enhanced implementation
// e.g. to use `react-native-reanimated` (see `reanimated` folder in repo)
const ScreenContext = React.createContext(Screen);
// e.g. to use `useReanimatedTransitionProgress` (see `reanimated` folder in repo)
const ScreenContext = React.createContext(InnerScreen);

class Screen extends React.Component<ScreenProps> {
static contextType = ScreenContext;

render() {
const ScreenWrapper = this.context || InnerScreen;
return <ScreenWrapper {...this.props} />;
}
}
Comment on lines +414 to +421
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could use a functional syntax here eg.:

const Screen = React.forwardRef<any, any>(function Screen(props, ref) {
  const TurboScreen = React.useContext(ScreenContext);
  const ScreenWrapper = TurboScreen || InnerScreen;
  return <ScreenWrapper {...props} ref={ref} />;
});

which I think here is more complicated than the class-based.


module.exports = {
// these are classes so they are not evaluated until used
Expand All @@ -418,6 +427,7 @@ module.exports = {
ScreenContainer,
ScreenContext,
ScreenStack,
InnerScreen,

get NativeScreen() {
return ScreensNativeModules.NativeScreen;
Expand Down
2 changes: 2 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export class NativeScreen extends React.Component<ScreenProps> {

export const Screen = Animated.createAnimatedComponent(NativeScreen);

export const InnerScreen = View;

export const ScreenContext = React.createContext(Screen);

export const ScreenContainer: React.ComponentType<ScreenContainerProps> = View;
Expand Down
4 changes: 2 additions & 2 deletions src/reanimated/ReanimatedNativeStackScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { Platform } from 'react-native';
import {
Screen,
InnerScreen,
ScreenProps,
TransitionProgressEventType,
} from 'react-native-screens';
Expand All @@ -11,7 +11,7 @@ import Animated, { useEvent, useSharedValue } from 'react-native-reanimated';
import ReanimatedTransitionProgressContext from './ReanimatedTransitionProgressContext';

const AnimatedScreen = Animated.createAnimatedComponent(
(Screen as unknown) as React.ComponentClass
(InnerScreen as unknown) as React.ComponentClass
);

// We use prop added to global by reanimated since it seems safer than the one from RN. See:
Expand Down
4 changes: 2 additions & 2 deletions src/reanimated/ReanimatedScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { Screen, ScreenProps } from 'react-native-screens';
import { InnerScreen, ScreenProps } from 'react-native-screens';

// @ts-ignore file to be used only if `react-native-reanimated` available in the project
import Animated from 'react-native-reanimated';

const AnimatedScreen = Animated.createAnimatedComponent(
(Screen as unknown) as React.ComponentClass
(InnerScreen as unknown) as React.ComponentClass
);

const ReanimatedScreen = React.forwardRef<typeof AnimatedScreen, ScreenProps>(
Expand Down