React Navigation after login navigate problem - javascript

I'm using useNavigation in React Navigation. After logging in with AsyncStorage, I want to redirect to the home page, but I cannot go back to the App function. When I want to go to HomePage, Navigate cannot find it and returns an error.
How can I trigger a function named app?
Navigate Error (console)
The action 'NAVIGATE' with payload {"name":"HomeScreen"} was not
handled by any navigator
Login Code
await AsyncStorage.setItem("userData", JSON.stringify(data.data));
navigation.navigate('HomeScreen');
App.js
const App = () => {
const [signedIn, setSignedIn] = useState([]);
useEffect(() => {
_checkUser();
}, []);
async function _checkUser(){
let responseUser = await AsyncStorage.getItem("userData");
setSignedIn(responseUser);
}
if(signedIn != null) {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="HomeScreen" component={_homeScreen} />
</Stack.Navigator>
</NavigationContainer>
)
} else {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
}
When I try to do it with MOBX..
let signedIn = userStore.isLogin;
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}}>
{
signedIn ? (
<Stack.Screen name="HomeScreen" component={_homeScreen} />
) : (
<>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</>
)
}
</Stack.Navigator>
</NavigationContainer>
)
Router
let data = await axios.post(baseURL+"users_checkMail", sendData);
uaStore.userStore.userData = data.data;
uaStore.userStore.isLogin = true;
await AsyncStorage.setItem("userData", JSON.stringify(data.data));
console.log(userStore.isLogin); // LOG: TRUE
setLoader(false);
navigation.navigate('HomeScreen');

If you are using mobx for state management, create and manage signedIn state in your mobx state tree. when user logs in , you just have to set signedIn state to true. When user logs out, set signedIn to false. No need to use navigation props. When you change your signedIn state, react-navigation component will rerender.

From the docs:
It's important to note that when using such a setup, you don't need to manually navigate to the Home screen by calling navigation.navigate('Home') or any other method. React Navigation will automatically navigate to the correct screen when isSigned in changes - Home screen when isSignedIn becomes true, and to SignIn screen when isSignedIn becomes false. You'll get an error if you attempt to navigate manually.
https://reactnavigation.org/docs/auth-flow/
So just remove the line:
navigation.navigate('HomeScreen');
And replace it with:
setSignedIn(true)
Or the MobX equivalent if you use MobX.

You can try like this
return (
<NavigationContainer>
{signedIn != null ? (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="HomeScreen" component={_homeScreen} />
</Stack.Navigator>
) : (
<Stack.Navigator screenOptions={{headerShown: false}}>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen name="EmailCodeScreen" component={_emailCodeScreen} />
</Stack.Navigator>
)}
</NavigationContainer>
);

First of all you cant use NavigationContainer twice..I would suggest make two Navigator like this one Login and another AppStack like this! I would just use redux and redux persist with async storage,makes life easier
const App = () => {
useEffect(() => {
setTimeout(() => {
RNBootSplash.hide({fade: true});
}, 1000);
}, []);
const LoginStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Login"
component={Login}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
<Stack.Screen
name="Terms"
component={Terms}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalPresentationIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
</Stack.Navigator>
);
};
const AppStack = () => {
return (
<Stack.Navigator>
{screens.map((screen, i) => (
<Stack.Screen
name={screen.name}
component={screen.screenname}
key={i}
options={{
headerTransparent: true,
cardStyle: {backgroundColor: colors.BACKGROUND},
...TransitionPresets.ModalSlideFromBottomIOS,
headerTitleStyle: {color: 'transparent'},
}}
/>
))}
</Stack.Navigator>
);
};
const AppState = () => {
const checkLoggedIn = useSelector((state) => state.AuthReducer.loggedIn);
return <>{checkLoggedIn === false ? <LoginStack /> : <AppStack />}</>;
};
return (
<Provider store={store}>
<NavigationContainer>
<AppState />
</NavigationContainer>
</Provider>
);
};
store.js
import {applyMiddleware, createStore} from 'redux';
import thunk from 'redux-thunk';
import AsyncStorage from '#react-native-async-storage/async-storage';
import {persistStore, persistReducer} from 'redux-persist';
import rootReducer from './index';
// Middleware: Redux Persist Config
const persistConfig = {
// Root
key: 'root',
// Storage Method (React Native)
storage: AsyncStorage,
// Whitelist (Save Specific Reducers)
whitelist: ['StickerReducer', 'AuthReducer'],
// Blacklist (Don't Save Specific Reducers)
blacklist: [''],
};
// Middleware: Redux Persist Persisted Reducer
const persistedReducer = persistReducer(persistConfig, rootReducer);
const middleware = [thunk];
const store = createStore(persistedReducer, applyMiddleware(...middleware));
// Middleware: Redux Persist Persister
let persistor = persistStore(store);
// Exports
export {store, persistor};
Auth Reducer
import {ADD_DEVICE_TOEKN, LOGGED_IN} from './types';
const initialState = {
loggedIn: false,
user_Id: '',
device_token: '',
};
export default AuthReducer = (state = initialState, action) => {
switch (action.type) {
case LOGGED_IN:
const paylodLoggedIn = action.payload;
return {
...state,
loggedIn: paylodLoggedIn.loggedIn,
user_Id: paylodLoggedIn.loggedIn,
};
case ADD_DEVICE_TOEKN:
const paylodToken = action.payload;
return {
...state,
device_token: paylodToken,
};
default:
return state;
}
};
import {combineReducers} from 'redux';
import AuthReducer from './AuthReducer';
import StickerReducer from './StickerReducer';
export default combineReducers({
AuthReducer: AuthReducer,
StickerReducer: StickerReducer,
});
Authaction.js
import {LOGGED_IN} from '../types';
export const LoginAction = (userData) => {
return (dispatch) => {
dispatch({
type: LOGGED_IN,
payload: userData,
});
};
};
Finally login dispacther
import {useDispatch} from 'react-redux';
import {LoginAction} from '../../../redux/actions/LoginAction';
const Login = ({navigation}) => {
const dispatch = useDispatch();
return (
<Pressable onPress={() =>dispatch(LoginAction(data))}>
</Pressable>
);
};

If you wanna trigger the App.js after successfull login ... then You need to wrap your NavigationContainer with React.Context
Your signedIn user is an object I think ... not an array
so by initalizing it in state with [] ... if(signedIn != null) will never evaluate to true ++ Make sure you JSON.parse your object after fetching it from AsyncStorage ...
const AuthContext = React.createContext({
signedIn,
_checkUser: () => {},
});
export const useAuth = () => React.useContext(AuthContext);
const defaultValue = {
signedIn,
_checkUser,
};
return (
<AuthContext.Provider value={defaultValue}>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
{signedIn ? (
<Stack.Screen name="HomeScreen" component={_homeScreen} />
) : (
<>
<Stack.Screen name="WelcomeScreen" component={_welcomeScreen} />
<Stack.Screen name="RegisterScreen" component={_registerScreen} />
<Stack.Screen name="LoginScreen" component={_loginScreen} />
<Stack.Screen name="ForgotScreen" component={_forgotScreen} />
<Stack.Screen
name="EmailCodeScreen"
component={_emailCodeScreen}
/>
</>
)}
</Stack.Navigator>
</NavigationContainer>
</AuthContext.Provider>
);
In LoginScreen
// Then you refresh you auth user in LoginScreen like
const { _checkUser } = useAuth();
_checkUser();

I had the same error when trying to use the useNavigation hook... I was able to resolve it using the dispatch method...
import { CommonActions } from '#react-navigation/native';
navigation.dispatch(
CommonActions.navigate({ name: 'Profile', params: { user: 'jane' }})
);
I created a utility function for less repetition...
const handleNavigate = (key: string) => {
navigation.dispatch(CommonActions.navigate({ name: key }));
};
// Usage
handleNavigate("Home")
This got rid of the error for me. Hope this helps

Related

react native firebase onAuthStateChanged not working

I'm querying if the user has logged in before. I want to have them go to different pages based on the result. onChangeState not working
import { firebase } from './config';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function App() {
const [initializing, setInitializin] = useState(true);
const [user, setUser] = useState('');
function onAuthStateChanged(user) {
setUser(user);
if (initializing) setInitializin(false);
}
useEffect(() => {
const subscriber = firebase.auth().onAuthStateChanged(onAuthStateChanged);
return subscriber;
}, []);
if (initializing) return null;
if (!user) {
return (
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen
name='Login'
component={LoginScreen}
options={{ headerShown: false, headerBackVisible: false }}
/>
<Stack.Screen
name='Create'
component={CreateAccount}
options={{ headerShown: true, headerTitle: 'Create An Account' }} />
</Stack.Navigator>
</NavigationContainer>
);
} else if (user)
return (
<NavigationContainer independent={true}>
<Stack.Navigator>
<Stack.Screen
name='Daily'
component={DailyScreen}
options={{ headerShown: false, headerBackVisible: false }} />
<Stack.Screen
name='Detail'
component={Detail}
options={{ headerShown: false, headerBackVisible: false }} />
</Stack.Navigator>
</NavigationContainer>
); return (
<NavigationContainer>
<App />
</NavigationContainer>
);
}
export default () => {
return (
<NavigationContainer independent={true}>
<App />
</NavigationContainer>
)
}
I want it to go to the DailyScreen page if the user has logged in before. But it always goes to the LoginScreen page.
Try this
change
const [user, setUser] = useState('');
to
const [user, setUser] = useState(null);

useEffect doesn't work when switching screens

Hi I am still new to react-native and has been trying to create an app.
My stuck is that I don't know why useEffect doesn't work when switching screens by react-navigation-bottom-tab.
Below is my HomeScreen.js where I wrot useEffect to fetch all data from Firestore.
As you can see I wrote two useEffects because I thought it'd work.
The first one was thought to fetch data when I switch to Home from like ProfileScreen.
import {
View,
FlatList,
StyleSheet,
} from "react-native";
import { RideCard } from "./RideCard";
import { OneTouchFilter } from "./OneTouchFilter";
import { useFirestoreContext } from "../../contexts/FirestoreContext";
import { useEffect } from "react";
export const HomeScreen = ({ navigation }) => {
console.log("HomeScreen.js useEffect");
const { selectedBoardType, cityFromText, cityToText, fetchRides, rides } =
useFirestoreContext();
useEffect(() => {
fetchRides();
}, []);
useEffect(() => {
fetchRides();
}, [selectedBoardType, cityFromText, cityToText]);
return (
<View style={styles.inner}>
<OneTouchFilter />
<FlatList
data={rides}
renderItem={(itemData) => (
<RideCard
ride={itemData.item}
index={itemData.index}
id={itemData.item.id}
numOfRides={rides.length}
/>
)}
/>
</View>
);
};
App.js
this is a file where react-navigation-bottom-tab placed in.
import React, { useContext } from "react";
import { StyleSheet } from "react-native";
import { NavigationContainer, DefaultTheme } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import { HomeScreen } from "./screens/Home/HomeScreen";
import { PostScreen } from "./screens/Post/PostScreen";
import { ProfileScreen } from "./screens/Profile/ProfileScreen";
import Ionicons from "react-native-vector-icons/Ionicons";
import { NativeBaseProvider } from "native-base";
// create another file for contexts Provider
import { AuthContextProvider } from "./contexts/AuthContext";
import { FirestoreContextProvider } from "./contexts/FirestoreContext";
import { FormContextProvider } from "./contexts/FormContext";
const MyTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: "white",
},
};
export default function App() {
const Stack = createStackNavigator();
// タブ移動の設定を新規追加
// createBottomTabNavigator ... タブ移動を設定する関数
const Tab = createBottomTabNavigator();
// 新規追加
// - 移動を関数に持たせて、タブ移動の設定で利用
// - 意図 ... タブ移動の箇所のコードが読みにくくなるため
const Home = () => {
return (
<Stack.Navigator>
<Stack.Screen
options={{ headerShown: false }}
name="Home"
component={HomeScreen}
/>
</Stack.Navigator>
);
};
const Post = () => {
return (
<Stack.Navigator
headerMode="screen"
screenOptions={{ headerShown: false }}
>
<Stack.Screen name="Post" component={PostScreen} />
{/* <Stack.Screen name="詳細" component={DetailsScreen} /> */}
</Stack.Navigator>
);
};
const Profile = () => {
return (
<Stack.Navigator
headerMode="screen"
screenOptions={{ headerShown: false }}
>
<Stack.Screen name="Profile" component={ProfileScreen} />
{/* <Stack.Screen name="詳細" component={DetailsScreen} /> */}
</Stack.Navigator>
);
};
return (
<AuthContextProvider>
<FirestoreContextProvider>
<FormContextProvider>
<NativeBaseProvider>
<NavigationContainer theme={MyTheme}>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
// icon swithcer which depends on the route name
if (route.name === "Home") {
iconName = focused ? "ios-home" : "ios-home";
} else if (route.name === "Post") {
iconName = focused ? "ios-add" : "ios-add";
} else if (route.name === "Profile") {
iconName = focused ? "md-person" : "md-person";
}
return (
<Ionicons name={iconName} size={size} color={color} />
);
},
})}
tabBarOptions={{
activeTintColor: "rgb(0, 110, 182)",
inactiveTintColor: "gray",
}}
>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Post" component={Post} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
</NativeBaseProvider>
</FormContextProvider>
</FirestoreContextProvider>
</AuthContextProvider>
);
}
It's because, even though you switch screens, the other screen is not unmounted --- it's still in memory but not visible. This is a design decision of react-navigation intended for better performance (it doesn't have to reload the screen when you go back, as it's already there). Since it is not unmounted, when the user returns to it, it just triggers a rerender of the already-instantiated component, so the effect does not run.
What you need to use instead is useFocusEffect which is an effect bound to if the screen is in focus.

React Navigation - Go back to a screen in another Navigator

I have a createBottomTabNavigator() in a screen of my createStackNavigator.
Basically i have my App.js like this :
const RootStack = createStackNavigator(
{
Login: Login,
Register: Register,
Principal: {
screen: Principal,
navigationOptions: {
headerShown: false,
},
},
},
{
initialRouteName: "Login"
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
And in my "Principal.js" i'm creating a createBottomTabNavigator()
const Tab = createBottomTabNavigator();
class ConnectNavigator extends React.Component {
(....)
render() {
return (
<NavigationContainer>
<Tab.Navigator (....)>
<Tab.Screen name="Home" component={CheckPage} />
<Tab.Screen name="Settings" component={SettingPage} />
</Tab.Navigator>
</NavigationContainer>
);
}
}
Basically, in my SettingPage, i want to go back in my "Login" screen. But because i have two Navigator, i can't. I know, i'm not very clear, but my question is : "Can i go in my Login Screen when i'm in a Tab.Screen ?"
I have already tried to do this.props.navigation.navigate('Login') in my Settings screen but i have this error
The action 'NAVIGATE' with payload {"name":"Login","params":{"screen":"Login"}} was not handled by any navigator.
Do you have a screen named 'Login'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
I'm not sure if you tried what's written in the documentation mentioned in the error, but you could try something like this:
navigation.navigate('Home', { screen: 'Login' });
Edit:
You could re-structure it a bit:
const AppNavigation = () => <NavigationContainer>
<Stack.Navigator initialRouteName={"Login"}>
<Stack.Screen
name={"Login"}
options={{
headerStyle: styles.loginHeader,
headerShown: false,
}}
component={LaunchScreen}
/>
<Stack.Screen
options={{ headerShown: false }}
name={"Principal"}
component={BottomTabNavigation}
/>
</NavigationContainer>
const Tab = createBottomTabNavigator()
const BottomTabNavigation = () => {
return (
<Tab.Navigator
initialRouteName={"Home"}
>
<Tab.Screen name="Home" component={CheckPage} />
<Tab.Screen name="Settings" component={SettingPage} />
</Tab.Navigator>
)
}

On first launch choose language React Native

I'm new to react native and using I18n to translate my multi language app according to user choice.
My main goal here is to show screen on first entry to the app that will decide the user language by his choice.
import React from 'react';
import Login from './login.js';
import Register from './register.js';
import Dashboard from './dashboard.js';
import { NavigationContainer, useNavigation } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { Text, View, Button } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
const HAS_LAUNCHED = 'hasLaunched';
const ENGLISH = 'en';
const HEBREW = 'he';
function setAppLaunched(en) {
const navigation = useNavigation();
AsyncStorage.setItem(HAS_LAUNCHED, 'true');
AsyncStorage.setItem(en ? ENGLISH : HEBREW, 'true');
navigation.navigate('Login');
}
async function checkIfFirstLaunch() {
try {
const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
if (hasLaunched === null) {
return (
<View>
<Text>Choose Language</Text>
<Button onPress={() => setAppLaunched(false)} title="Hebrew"/>
<Button onPress={() => setAppLaunched(true)} title="English"/>
</View>
);
}
return false;
} catch (error) {
return false;
}
}
console.log(checkIfFirstLaunch());
const Stack = createStackNavigator();
export default function App() {
return (
<>
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="Dashboard" component={Dashboard} />
</Stack.Navigator>
</NavigationContainer>
</>
);
}
Once checkIfFirstLaunch() is triggered AsyncStorage saves the user language and remember it to the next times he launches the app.
I have created the syntax that will detect if user launched the app for the first time, but how can I actually show that screen?
How to display first launch screen using functional components?
EDIT
export default function App() {
return (
<>
<CheckIfFirstLaunch/>
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="Dashboard" component={Dashboard} />
</Stack.Navigator>
</NavigationContainer>
</>
);
}
If I try that it returns the following
Error: Objects are not valid as a React child (found: object with keys
{_U, _V, _W, _X}). If you meant to render a collection of children,
use an array instead.
The error is because you're rendering a Functional Component that you defined as an async function.
Now I don't know if you want to show the "Choice" and the navigation screens at the same time. If you want that, maintain the structure you have and do this.
function checkIfFirstLaunch() {
const [selected, setSelected] = useState(false);
if (selected) return null;
const verifyHasLaunched = async () => {
try {
const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
setSelected(hasLaunched != null)
} catch (err) {
setSelected(false);
}
}
useEffect(verifyHasLaunched);
const selectLaunched = (value) => {
setAppLaunched(value);
setSelected(true);
};
return (
<View>
<Text>Choose Language</Text>
<Button onPress={() => selectLaunched(false)} title="Hebrew"/>
<Button onPress={() => selectLaunched(true)} title="English"/>
</View>
);
}
If you need to change the render as in render either the "Choose screen" or the Navigation component
Then you have to change both App and checkIfFirstLaunch;
function checkIfFirstLaunch({ onSelect }) {
const selectLaunched = (value) => {
setAppLaunched(value);
onSelect();
};
return (
<View>
<Text>Choose Language</Text>
<Button onPress={() => selectLaunched(false)} title="Hebrew"/>
<Button onPress={() => selectLaunched(true)} title="English"/>
</View>
);
}
export default class App extends React.Component {
state = {
selected: false;
};
async componentDidMount() {
try {
const hasLaunched = await AsyncStorage.getItem(HAS_LAUNCHED);
this.setState({ selected: hasLaunched != null })
} catch (err) {
// Something went wrong
}
}
render() {
if (!this.state.selected) return <CheckIfFirstLaunch onSelect={() => this.setState({ selected: true })} />
return (
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown: false}} initialRouteName="Login">
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Register" component={Register} />
<Stack.Screen name="Dashboard" component={Dashboard} />
</Stack.Navigator>
</NavigationContainer>
);
}
}

React Native, how do I pass params to a screen when pressing the tab in a tab navigator?

I have a function using the stack navigator, and inside of that is a nested tab navigator. After obtaining a code on the "ConnectScreen" I want to pass the code to "FeedScreen" inside of the tab navigator. The code is accessible as route.params.code in the Home function. I then want to pass the code to FeedScreen.
function ConnectScreen({ navigation, route }) {
const [request, response, promptAsync] = useAuthRequest(
{
clientId: 'xxx',
scopes: [
"user-top-read",
"user-read-currently-playing",
"user-read-playback-state",
"user-modify-playback-state",
],
usePKCE: false,
redirectUri: makeRedirectUri({
native: 'your.app://redirect',
}),
},
discovery
);
const [state, setState] = React.useState({
token: null
})
React.useEffect(() => {
if (response?.type === 'success') {
var clientId = 'xxx'
var clientSecret = 'xxx'
var credsB64 = btoa(`${clientId}:${clientSecret}`)
var accessCode = response.params.code
var redirectUri = "xxx"
}
const tokenResponse = fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
Authorization: `Basic ${credsB64}`,
},
body: `grant_type=authorization_code&code=${accessCode}&redirect_uri=${redirectUri}`,
}).then((response) => response.json())
.then((responseJSON) => {
if (responseJSON.access_token) {
var token = responseJSON.access_token
setState({
token: token
})
}
})
}, [response]);
return (
<View style={styles.container}>
<Button
disabled={!request}
title="Connect to Spotify"
onPress={() => {
promptAsync()
}}
/>
<Button
title="Home"
onPress={() =>
navigation.navigate('Home', {
screen: 'FeedScreen',
params: {
code: state.token,
}
})
}
/>
</View>
);
}
class FeedScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
const HomeTab = createBottomTabNavigator();
function Home({ route}) {
console.log("HOME TAB ROUTE",route.params.code)
return (
<HomeTab.Navigator>
<HomeTab.Screen name= "Feed" component={FeedScreen} />
<HomeTab.Screen name= "Player" component={PlayerScreen} />
<HomeTab.Screen name= "Search" component={SearchScreen} />
</HomeTab.Navigator>
)
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Splash"
component={SplashScreen}
/>
<Stack.Screen
name="Login"
component={LoginScreen}
/>
<Stack.Screen
name="Connect"
component={ConnectScreen}
/>
<Stack.Screen
name="Home"
component={Home}
/>
</Stack.Navigator>
</NavigationContainer>
You can navigate to FeedScreen directly from ConnectScreen
navigation.navigate('Home', { screen: 'FeedScreen ', params: {code: yourCode} });
Try this way
<HomeTab.Screen name="home" children={()=><ComponentName propName={propValue}/>} />
You can checkout react-navigation for navigation actions. Basically, you can create specific methods for specific actions Stack and Navigation based.
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
const Stack = createStackNavigator();
const MyStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Welcome' }}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
</NavigationContainer>
);
};
You can find StackActions: StackActions
You can find NavigationActions: NavigationActions
I prefer NavigationService.js file to navigate and manage the stack.
// NavigationService.js
import { NavigationActions } from 'react-navigation';
let _navigator;
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
})
);
}
// add other navigation functions that you need and export them
export default {
navigate,
setTopLevelNavigator,
};

Categories

Resources