I pretty much followed both react-navigation deep linking and branch.io react-native documentation, and either both are deprecated or just not completely helpful.
All I want is that whenever a deep link reads from the linking, navigate to a certain screen, I'm not looking to implement a listener on a specific screen, I want this on a root path, and is either the onReady (which for me didn't work) or linking from navigator container
this is my code, very simple
const linking: LinkingOptions = {
prefixes: ['agendameio://', 'https://agendame.io', 'https://agendameio.app.link', 'https://agendameio.app-alternative.link'],
subscribe(listener) {
const navigation = useNavigation();
const onReceiveURL = ({ url }: { url: string }) => listener(url);
Linking.addEventListener('url', onReceiveURL);
branch.skipCachedEvents();
branch.subscribe(async ({ error, params, uri }) => {
if (error) {
console.error('Error from Branch: ' + error);
return;
}
if (params) {
DataManager.DynamicURL = params['~id'] === "951933826563912687" ? params.id : undefined;
}
let url = params?.['+url'] || params?.['~referring_link']; // params !== undefined ? `agendameio://empresa/${params.id}` : 'agendameio://empresa';
navigation.navigate(`DetalleEmpresa${params.id}`);
listener(url);
});
return () => {
Linking.removeEventListener('url', onReceiveURL);
branch.logout();
};
},
I instantly get an error due to use navigation, but I really don't know what else to use to navigate to inside the app
EDIT: this is the error in particular
EDIT 2: I'll add my navigation so it can help to understand my problem
function firstStack() {
return (
<homeStack.Navigator initialRouteName="EmpresasScreen">
<homeStack.Screen
options={({navigation}) => ({
headerShown: false,
headerTitle: () => (
<>
<View style={styles.viewHeader}>
<Image
resizeMode="contain"
style={styles.imageLogo}
source={Images.iconoToolbar}
/>
</View>
</>
),
})}
name="EmpresasScreen"
component={EmpresasScreen}
/>
<detalleEmpresaStack.Screen
options={{ headerShown: false }}
name="DetalleEmpresaScreen"
component={DetalleEmpresaScreen}
/>
<agendamientoStack.Screen
options={{ headerShown: false }}
name="AgendamientoScreen"
component={AgendamientoScreen}
/>
</homeStack.Navigator>
);
}
function secondStack() {
return (
<misCitasStack.Navigator>
<misCitasStack.Screen
options={({navigation}) => ({
headerShown: false,
headerTitle: () => (
<>
<View style={styles.viewHeader}>
<Image
resizeMode="contain"
style={styles.imageLogo}
source={Images.iconoToolbar}
/>
</View>
</>
),
})}
name="MisCitasScreen"
component={CitasScreen}
/>
<detalleCitasStack.Screen
options={({navigation}) => ({
headerShown: false,
})}
name="DetalleCitaScreen"
component={DetalleCitaScreen}
/>
</misCitasStack.Navigator>
);
}
function tabStack() {
return (
<tab.Navigator
screenOptions={({route}) => ({
tabBarIcon: ({focused}) => {
let iconName;
if (route.name === 'Home') {
iconName = focused
? Images.casaActive
: Images.casa
} else if (route.name === 'Citas') {
iconName = focused
? Images.citasActive
: Images.citas
}
return <Image source={iconName} />
}
})}
tabBarOptions={{
showLabel: false,
}}>
<tab.Screen name="Home" component={firstStack} />
<tab.Screen name="Citas" component={secondStack} />
</tab.Navigator>
);
}
function menuStackNavigator() {
useEffect(() => {
VersionCheck.needUpdate({forceUpdate: true}).then(async res => {
if (res.isNeeded) {
alertNeedUpdate(res.storeUrl, false);
}
});
if(Platform.OS === 'android') {
NativeModules.SplashScreenModule.hide();
}
}, [])
return (
<NavigationContainer linking={linking}>
<stack.Navigator headerMode="none">
<stack.Screen name="Home" component={tabStack} />
<stack.Screen name="Error" component={ErrorScreen} />
</stack.Navigator>
</NavigationContainer>
);
};
const styles = StyleSheet.create({
viewHeader: {
alignItems: 'center',
justifyContent: 'center',
},
imageLogo: {
alignItems: 'center',
justifyContent: 'center',
marginTop: 6,
marginBottom: 6
}
});
export default menuStackNavigator;
see more example here configuring-links
Here the URL /feed
will open screen named Chat
.
import { NavigationContainer } from '@react-navigation/native';
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort', //URL `/feed` will open screen named `Chat`.
Profile: 'user',
}
},
};
function App() {
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
<Stack.Navigator>
<Stack.Screen name="Chat" component={ChatScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
navigationRef
.read about it navigating-without-navigation-prop.
wait to navigation to be ready and then navigate.
import { createNavigationContainerRef } from '@react-navigation/native';
function App() {
const navigationRef = createNavigationContainerRef();
const navigateWhenNavigationReady = (routeName, params, n = 0) => {
setTimeout(() => {
if (navigationRef?.getRootState()) {
navigationRef.navigate(routeName, params)
}else if (n < 100) {
navigateWhenNavigationReady(routeName, params, n + 1);
}
}, 300)
}
const linking = {
...,
subscribe(listener) {
...
navigateWhenNavigationReady("Chat", {id: 123});
}
};
return (
<NavigationContainer ref={navigationRef} linking={linking}>
<Stack.Navigator>
<Stack.Screen name="Chat" component={ChatScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}