Skip to content

Commit

Permalink
fix: wrap Screen with ScreenContext (#1539)
Browse files Browse the repository at this point in the history
* fix: wrap screen with screen context

* chore: add reproduction

* chore: make tests self-contained
  • Loading branch information
kacperkapusciak authored Jul 25, 2022
1 parent 7e4a348 commit 67d1fd1
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 61 deletions.
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} />;
}
}

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

0 comments on commit 67d1fd1

Please sign in to comment.