So, I am building a prototype android app as an internship project for a startup in React Native v0.66. I was new to RN but not React when I set up the project. My choice for navigation fell upon React Navigation 6.x and their Native Stack Navigator because it performs better than the regular Stack Navigator, although is not as customizable according to docs.
Now I want to use react-native-gesture-handler in my project. According to their docs,
"If you are using a native navigation library like wix/react-native-navigation you need to follow a different setup for your Android app to work properly. The reason is that both native navigation libraries and Gesture Handler library need to use their own special subclasses of ReactRootView.
Instead of changing Java code you will need to wrap every screen component using gestureHandlerRootHOC on the JS side. This can be done for example at the stage when you register your screens."
I suppose this includes React Navigation-Native Stack Navigator as well? There is code example of how to implement RNGH with wix/react-native-navigation, but none, anywhere, for my case:
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
import { Navigation } from 'react-native-navigation';
import FirstTabScreen from './FirstTabScreen';
import SecondTabScreen from './SecondTabScreen';
import PushedScreen from './PushedScreen';
// register all screens of the app (including internal ones)
export function registerScreens() {
Navigation.registerComponent(
'example.FirstTabScreen',
() => gestureHandlerRootHOC(FirstTabScreen),
() => FirstTabScreen
);
Navigation.registerComponent(
'example.SecondTabScreen',
() => gestureHandlerRootHOC(SecondTabScreen),
() => SecondTabScreen
);
Navigation.registerComponent(
'example.PushedScreen',
() => gestureHandlerRootHOC(PushedScreen),
() => PushedScreen
);
}
My app.js (where I set up the Native Stack Navigator) look like this:
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
import React from 'react';
import { Provider } from 'react-redux';
import { Store } from './redux/store';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MenuScreen from './screens/Menu';
import HomeScreen from './screens/Home';
import MyShopsScreen from './screens/MyShops';
import AddProductScreen from './screens/AddProduct';
import ProductDetailsScreen from './screens/ProductDetails';
const Stack = createNativeStackNavigator();
function App() {
return (
<Provider store={Store}>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Menu" component={MenuScreen} />
<Stack.Screen name="MyShops" component={MyShopsScreen} />
<Stack.Screen name="AddProduct" component={AddProductScreen} />
<Stack.Screen name="ProductDetails" component={ProductDetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
</Provider>
);
};
export default App;
I really want to do the setup the right way before I start trying to get gesture handlers to work, as I otherwise might not be able to tell if it's the setup or my implementation of a gesture handler that is wrong.
Is it as easy as wrapping a screen:
<Stack.Screen name="Home" component={HomeScreen} />
to
<Stack.Screen name="Home" component={gestureHandlerRootHOC(HomeScreen)} />
?
Or do I wrap the individual component needing a gesture handler in gestureHandlerRootHOC(), like so:
export default gestureHandlerRootHOC(someComponent)
or am I way off? Any help welcome.
UPDATE:
I implemented react-native-vision-camera in the project and browsed the example app. Happy was I when I saw author mrousavy using Native Stack Navigator and react-native-gesture-handler together. He uses react-native-reanimated too though:
//#region Pinch to Zoom Gesture
// The gesture handler maps the linear pinch gesture (0 - 1) to an exponential curve since a camera's zoom
// function does not appear linear to the user. (aka zoom 0.1 -> 0.2 does not look equal in difference as 0.8 -> 0.9)
const onPinchGesture = useAnimatedGestureHandler<PinchGestureHandlerGestureEvent, { startZoom?: number }>({
onStart: (_, context) => {
context.startZoom = zoom.value;
},
onActive: (event, context) => {
// we're trying to map the scale gesture to a linear zoom here
const startZoom = context.startZoom ?? 0;
const scale = interpolate(event.scale, [1 - 1 / SCALE_FULL_ZOOM, 1, SCALE_FULL_ZOOM], [-1, 0, 1], Extrapolate.CLAMP);
zoom.value = interpolate(scale, [-1, 0, 1], [minZoom, startZoom, maxZoom], Extrapolate.CLAMP);
},
});
//#endregion
I can't find the use of gestureHandlerRootHOC() anywhere either but at least I know it's possible combining react-native-gesture-handler and Native Stack Navigator.
I am still very much looking for a clean, basic solution similar to react-native-gesture-handler docs implementation with wix/react-native-navigation!
I simply went with:
<Stack.Screen name="Home" component={HomeScreen} />
to
<Stack.Screen name="Home" component={gestureHandlerRootHOC(HomeScreen)} />
and wrapped every screen like this. Works like a charm in all nested components too. Caveats or pitfalls with this approach are welcome. I'll accept this answer for now.