admin管理员组文章数量:1426029
I read Authentication flow tutorial for react navigation. I successfully integrated it. There is one thing I cannot get to work. It's "navigation" part in export default function App({ navigation })
.
What do I need to do for this to be functional. I get undefined
for navigation
variable. I need navigation in App.js because of React Native Firebase notifications. I integrated RN Firebase and Notifee.
Goal is to listen to foreground and background event and when I get notification and press on it to navigate to specific screen. Without navigation
I won't be able to do it.
Here is my App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import LoginScreen from './src/screens/LoginScreen.js'
import HomeScreen from './src/screens/tabs/HomeScreen.js'
import LogoutScreen from './src/screens/tabs/LogoutScreen.js'
import ContactsScreen from './src/screens/tabs/home/ContactsScreen.js'
import ConfirmPhoneNumberScreen from './src/screens/ConfirmPhoneNumberScreen.js'
import { createStackNavigator } from '@react-navigation/stack';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { ActivityIndicator, View, Text, Alert, Platform } from "react-native";
import { AppStyles } from "./src/AppStyles";
import Auth from './src/helpers/Auth.js';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import NetInfo from "@react-native-munity/netinfo";
import NoInternetScreen from './src/screens/NoInternetScreen.js';
import Trans from './src/helpers/Trans.js';
import Toast from 'react-native-toast-message';
import Firebase from './src/push_notifications/Firebase.js';
import messaging from '@react-native-firebase/messaging';
import LatestMessagesScreen from './src/screens/messages/LatestMessagesScreen.js';
const AuthContext = React.createContext();
const Stack = createStackNavigator();
const BottomTabs = createBottomTabNavigator();
const FirebaseClass = new Firebase();
const AuthClass = new Auth();
function App({navigation}) {
const [state, dispatch] = React.useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
userToken: action.token,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
isSignout: false,
userToken: action.token,
};
case 'SIGN_OUT':
return {
...prevState,
isSignout: true,
userToken: null,
};
case 'INTERNET_IS_ON':
return {
...prevState,
showNoInternetPage: false,
};
case 'INTERNET_IS_OFF':
return {
...prevState,
showNoInternetPage: true,
};
}
},
{
isLoading: true,
isSignout: false,
userToken: null,
showNoInternetPage: false,
}
);
React.useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
if (false === state.isInternetReachable && false === state.isConnected) {
dispatch({ type: 'INTERNET_IS_OFF' });
} else {
dispatch({ type: 'INTERNET_IS_ON' });
}
//console.log("Connection type", state.isInternetReachable); //none
//console.log("Is connected?", state.isConnected); //false
});
// Fetch the token from storage then navigate to our appropriate place
const bootstrapAsync = async () => {
let userToken;
try {
userToken = await AsyncStorage.getItem('@passwordAccessToken');
} catch (e) {
// Restoring token failed
}
// After restoring token, we may need to validate it in production apps
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away.
dispatch({ type: 'RESTORE_TOKEN', token: userToken });
};
bootstrapAsync();
FirebaseClass.requestUserPermission();
}, []);
const authContext = React.useMemo(
() => ({
confirmPhoneNumber: async data => {
data.navigation.navigate('ConfirmPhoneNumberScreen')
},
signIn: async data => {
// In a production app, we need to send some data (usually username, password) to server and get a token
// We will also need to handle errors if sign in failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
await AuthClass.getPasswordGrandTypeToken();
const accessToken = await AsyncStorage.getItem('@passwordAccessToken');
FirebaseClass.getPushToken();
dispatch({ type: 'SIGN_IN', token: accessToken });
},
signOut: () => {
AsyncStorage.removeItem('@passwordAccessToken');
dispatch({ type: 'SIGN_OUT' })
},
signUp: async data => {
// In a production app, we need to send user data to server and get a token
// We will also need to handle errors if sign up failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
},
}),
[]
);
createBottomTabs = () => {
const { signOut } = React.useContext(AuthContext);
return (
<BottomTabs.Navigator>
<BottomTabs.Screen name='HomeTab'
ponent={HomeScreen}
options={{
title: Trans.t('app.tabbar_home'),
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)
}}></BottomTabs.Screen>
<BottomTabs.Screen name='LogoutTab' ponent={LogoutScreen}
options={{
title: Trans.t('app.tabbar_logout'),
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="logout" color={color} size={size} />
)
}}
listeners={{
tabPress: e => {
e.preventDefault();
Alert.alert( // Shows up the alert without redirecting anywhere
Trans.t('alert.confirmation_title'),
Trans.t('alert.confirmation_body'),
[
{ text: Trans.t('alert.yes'), onPress: () => { signOut(); } },
{ text: Trans.t('alert.no') }
]
);
}
}}
></BottomTabs.Screen>
</BottomTabs.Navigator>
)
}
if (state.isLoading) {
// We haven't finished checking for the token yet
return (
<ActivityIndicator
style={{ marginTop: 200 }}
size="large"
color={AppStyles.color.tint}
/>
);
}
return (
<NavigationContainer>
<AuthContext.Provider value={authContext}>
<Stack.Navigator>
{(state.showNoInternetPage) ?
<>
<Stack.Screen
name="NoInternet"
ponent={NoInternetScreen}
options={{
headerTitle: Trans.t('app.no_internet_header')
}}
></Stack.Screen>
</> : (state.userToken == null) ? (
<>
<Stack.Screen name="Login" ponent={LoginScreen}
options={{
headerTitle: Trans.t('app.login_or_register_header'),
headerTitleAlign: 'center'
}} />
<Stack.Screen
name="ConfirmPhoneNumberScreen"
ponent={ConfirmPhoneNumberScreen}
options={{ headerTitle: Trans.t('app.confirm_phone_number_header') }} />
</>
) : (
<>
<Stack.Screen name="Home"
children={createBottomTabs}
options={{
headerTitle: Trans.t('app_name'),
headerTitleAlign: 'center'
}}></Stack.Screen>
<Stack.Screen
name='Contacts'
ponent={ContactsScreen}
></Stack.Screen>
<Stack.Screen
name='LatestMessages'
options={{
headerTitle: Trans.t('latest_messages_screen.header_title')
}}
ponent={LatestMessagesScreen}
></Stack.Screen>
</>
)}
</Stack.Navigator>
<Toast ref={(ref) => Toast.setRef(ref)} />
</AuthContext.Provider>
</NavigationContainer>
);
}
export default App;
export { AuthContext };
Here is my index.js
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in the Expo client or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
Can anybody help me with this?
I read Authentication flow tutorial for react navigation. I successfully integrated it. There is one thing I cannot get to work. It's "navigation" part in export default function App({ navigation })
.
What do I need to do for this to be functional. I get undefined
for navigation
variable. I need navigation in App.js because of React Native Firebase notifications. I integrated RN Firebase and Notifee.
Goal is to listen to foreground and background event and when I get notification and press on it to navigate to specific screen. Without navigation
I won't be able to do it.
Here is my App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import LoginScreen from './src/screens/LoginScreen.js'
import HomeScreen from './src/screens/tabs/HomeScreen.js'
import LogoutScreen from './src/screens/tabs/LogoutScreen.js'
import ContactsScreen from './src/screens/tabs/home/ContactsScreen.js'
import ConfirmPhoneNumberScreen from './src/screens/ConfirmPhoneNumberScreen.js'
import { createStackNavigator } from '@react-navigation/stack';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { ActivityIndicator, View, Text, Alert, Platform } from "react-native";
import { AppStyles } from "./src/AppStyles";
import Auth from './src/helpers/Auth.js';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import NetInfo from "@react-native-munity/netinfo";
import NoInternetScreen from './src/screens/NoInternetScreen.js';
import Trans from './src/helpers/Trans.js';
import Toast from 'react-native-toast-message';
import Firebase from './src/push_notifications/Firebase.js';
import messaging from '@react-native-firebase/messaging';
import LatestMessagesScreen from './src/screens/messages/LatestMessagesScreen.js';
const AuthContext = React.createContext();
const Stack = createStackNavigator();
const BottomTabs = createBottomTabNavigator();
const FirebaseClass = new Firebase();
const AuthClass = new Auth();
function App({navigation}) {
const [state, dispatch] = React.useReducer(
(prevState, action) => {
switch (action.type) {
case 'RESTORE_TOKEN':
return {
...prevState,
userToken: action.token,
isLoading: false,
};
case 'SIGN_IN':
return {
...prevState,
isSignout: false,
userToken: action.token,
};
case 'SIGN_OUT':
return {
...prevState,
isSignout: true,
userToken: null,
};
case 'INTERNET_IS_ON':
return {
...prevState,
showNoInternetPage: false,
};
case 'INTERNET_IS_OFF':
return {
...prevState,
showNoInternetPage: true,
};
}
},
{
isLoading: true,
isSignout: false,
userToken: null,
showNoInternetPage: false,
}
);
React.useEffect(() => {
const unsubscribe = NetInfo.addEventListener(state => {
if (false === state.isInternetReachable && false === state.isConnected) {
dispatch({ type: 'INTERNET_IS_OFF' });
} else {
dispatch({ type: 'INTERNET_IS_ON' });
}
//console.log("Connection type", state.isInternetReachable); //none
//console.log("Is connected?", state.isConnected); //false
});
// Fetch the token from storage then navigate to our appropriate place
const bootstrapAsync = async () => {
let userToken;
try {
userToken = await AsyncStorage.getItem('@passwordAccessToken');
} catch (e) {
// Restoring token failed
}
// After restoring token, we may need to validate it in production apps
// This will switch to the App screen or Auth screen and this loading
// screen will be unmounted and thrown away.
dispatch({ type: 'RESTORE_TOKEN', token: userToken });
};
bootstrapAsync();
FirebaseClass.requestUserPermission();
}, []);
const authContext = React.useMemo(
() => ({
confirmPhoneNumber: async data => {
data.navigation.navigate('ConfirmPhoneNumberScreen')
},
signIn: async data => {
// In a production app, we need to send some data (usually username, password) to server and get a token
// We will also need to handle errors if sign in failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
await AuthClass.getPasswordGrandTypeToken();
const accessToken = await AsyncStorage.getItem('@passwordAccessToken');
FirebaseClass.getPushToken();
dispatch({ type: 'SIGN_IN', token: accessToken });
},
signOut: () => {
AsyncStorage.removeItem('@passwordAccessToken');
dispatch({ type: 'SIGN_OUT' })
},
signUp: async data => {
// In a production app, we need to send user data to server and get a token
// We will also need to handle errors if sign up failed
// After getting token, we need to persist the token using `AsyncStorage`
// In the example, we'll use a dummy token
dispatch({ type: 'SIGN_IN', token: 'dummy-auth-token' });
},
}),
[]
);
createBottomTabs = () => {
const { signOut } = React.useContext(AuthContext);
return (
<BottomTabs.Navigator>
<BottomTabs.Screen name='HomeTab'
ponent={HomeScreen}
options={{
title: Trans.t('app.tabbar_home'),
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
)
}}></BottomTabs.Screen>
<BottomTabs.Screen name='LogoutTab' ponent={LogoutScreen}
options={{
title: Trans.t('app.tabbar_logout'),
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="logout" color={color} size={size} />
)
}}
listeners={{
tabPress: e => {
e.preventDefault();
Alert.alert( // Shows up the alert without redirecting anywhere
Trans.t('alert.confirmation_title'),
Trans.t('alert.confirmation_body'),
[
{ text: Trans.t('alert.yes'), onPress: () => { signOut(); } },
{ text: Trans.t('alert.no') }
]
);
}
}}
></BottomTabs.Screen>
</BottomTabs.Navigator>
)
}
if (state.isLoading) {
// We haven't finished checking for the token yet
return (
<ActivityIndicator
style={{ marginTop: 200 }}
size="large"
color={AppStyles.color.tint}
/>
);
}
return (
<NavigationContainer>
<AuthContext.Provider value={authContext}>
<Stack.Navigator>
{(state.showNoInternetPage) ?
<>
<Stack.Screen
name="NoInternet"
ponent={NoInternetScreen}
options={{
headerTitle: Trans.t('app.no_internet_header')
}}
></Stack.Screen>
</> : (state.userToken == null) ? (
<>
<Stack.Screen name="Login" ponent={LoginScreen}
options={{
headerTitle: Trans.t('app.login_or_register_header'),
headerTitleAlign: 'center'
}} />
<Stack.Screen
name="ConfirmPhoneNumberScreen"
ponent={ConfirmPhoneNumberScreen}
options={{ headerTitle: Trans.t('app.confirm_phone_number_header') }} />
</>
) : (
<>
<Stack.Screen name="Home"
children={createBottomTabs}
options={{
headerTitle: Trans.t('app_name'),
headerTitleAlign: 'center'
}}></Stack.Screen>
<Stack.Screen
name='Contacts'
ponent={ContactsScreen}
></Stack.Screen>
<Stack.Screen
name='LatestMessages'
options={{
headerTitle: Trans.t('latest_messages_screen.header_title')
}}
ponent={LatestMessagesScreen}
></Stack.Screen>
</>
)}
</Stack.Navigator>
<Toast ref={(ref) => Toast.setRef(ref)} />
</AuthContext.Provider>
</NavigationContainer>
);
}
export default App;
export { AuthContext };
Here is my index.js
import { registerRootComponent } from 'expo';
import App from './App';
// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
// It also ensures that whether you load the app in the Expo client or in a native build,
// the environment is set up appropriately
registerRootComponent(App);
Can anybody help me with this?
Share Improve this question edited Dec 14, 2020 at 20:37 FosAvance asked Dec 14, 2020 at 20:29 FosAvanceFosAvance 2,4799 gold badges40 silver badges54 bronze badges 1- Not sure but did you try to export default function() { const navigation = nav; return App(navigation);} or in index.js const expoApp = App(navigation); registerRootComponent(expoApp); – JB_DELR Commented Dec 14, 2020 at 22:31
1 Answer
Reset to default 6you first create a RootNavigation
, then you export is as your navigation class.
RootNavigation.js
import * as React from 'react';
export const isReadyRef = React.createRef();
export const navigationRef = React.createRef();
export function navigate(name, params) {
if (isReadyRef.current && navigationRef.current) {
// Perform navigation if the app has mounted
navigationRef.current.navigate(name, params);
} else {
// You can decide what to do if the app hasn't mounted
// You can ignore this, or add these actions to a queue you can call later
}
}
once you have the above, you need to reference it in your App.
import { navigationRef, isReadyRef } from './RootNavigation';
React.useEffect(() => {
return () => {
isReadyRef.current = false
};
}, []);
return (
<NavigationContainer ref={navigationRef}
onReady={() => {
isReadyRef.current = true;
}}>
<AuthContext.Provider value={authContext}>
once you did the above, you can use it anywhere in your app including App.js like so:
import * as RootNavigation from './path/to/RootNavigation.js';
// ...
RootNavigation.navigate('ChatScreen', { userName: 'Lucy' });
source: https://reactnavigation/docs/navigating-without-navigation-prop
本文标签: javascriptPassing navigation to Appjs in React NativeStack Overflow
版权声明:本文标题:javascript - Passing navigation to App.js in React Native - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745466186a2659543.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论