I am using the following code to display a 'Home' page with a button on it in React Native...it is functional without difficulty:
import React, { useState } from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button title="Go to Login" onPress={() => navigation.navigate('Login')} />
</View>
);
}
function LoginScreen({ navigation }) {
//do things to login here
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
The problem arises when I try to modify the code to display a button on the 'Home' page dependent on the value of a global variable, I get an error. I am not sure why however it may be the 'HomeScreen' function does not recognize the value of the '_secured' variable...?
import React, { useState } from 'react';
import { Button, Text, TextInput, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
var _secured = 0;
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
if (_secured === 0) {
<Button title="Go to Login" onPress={() => navigation.navigate('Login')} />
} else {
<Button title="Stuff" onPress={() => navigation.navigate('DoStuff')} />
}
</View>
);
}
function LoginScreen({ navigation }) {
//do things to login here
}
function StuffScreen({ navigation }) {
//do other things here
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="DoStuff" component={StuffScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Any suggestions greatly appreciated, I am new to React Native. I thank you in advance.
Unfortunately I am still having immense difficulty trying to figure this out, it is incredibly frustrating. I believe I need to define my 'global' variable using the 'useState'. My code for the 'Home' screen is as follows:
function HomeScreen({ navigation }) {
const [isLogged, setLog] = useState(0);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
(isLogged === 0) ? (<Button title="Go to Login"> onPress={() => navigation.navigate('Login')} </Button>) : (<Button title="Stuff"> onPress={() => navigation.navigate('DoStuff')} </Button>)
}
As previously mentioned I am new to developing for React Native. The inability to use simple if/else statements to accomplish this is extremely disheartening. I thank anybody in advance for some insight.
Just like an ordinary function, react renderer cannot return more than one JSX element. So wrapping up your original code inside a single JSX EmptyView <></> and then using JS to evaluate conditions and finally returning a button view.
function HomeScreen({ navigation }) {
const [isLogged, setLog] = useState(0);
return (
<>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
{isLogged === 0 ? (<Button title="Go to Login" onPress={() => navigation.navigate('Login')} > </Button>) : (<Button title="Stuff" onPress={() => navigation.navigate('DoStuff')} > </Button>)}
</>
);
}
Related
When i try passing the params to my review screen it comes up undefined.
I'm using "#react-navigation/native": "^6.1.3" and "#react-navigation/stack": "^6.3.12"
App.js
import 'react-native-gesture-handler';
import { StyleSheet, Text, View, Button, TouchableOpacity, FlatList } from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import Stack from './routes/stack';
export default function App() {
return (
<NavigationContainer>
<Stack/>
</NavigationContainer>
);
}
Stack.js
import {createStackNavigator} from '#react-navigation/stack';
import ReviewScreen from '../screens/Reviews';
import HomeScreen from '../screens/Home';
import AboutScreen from '../screens/About';
const stack = createStackNavigator();
const Stack = () => {
return(
<stack.Navigator>
<stack.Screen name="Home" component={HomeScreen} />
<stack.Screen name="Review" component={ReviewScreen} />
</stack.Navigator>
)}
export default Stack;
HomeScreen
<View style={{width: 100, alignItems: "center"}}>
<TouchableOpacity style={{backgroundColor: "#333", padding: 10, borderRadius: 15, margin: 10}}
onPress={() => navigation.navigate("Review",
{title:"Title Name"}
)}
>
<Text style={{color: "white"}}>{item.title}</Text>
</TouchableOpacity>
</View>
Review.js
import {View, Text, Button} from 'react-native';
import React from 'react';
export default ReviewScreen = ({ navigation, route }) => {
console.log(route);
const { title } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Review Screen</Text>
<Button
title="Go to Home"
onPress={() => navigation.goBack()}
/>
</View>
);
};
When I send the object from the home page to the review screen the destructed title throws an undefined error and when I log the route object it shows that the params value is undefined.
console logged route object
{"key": "Review-xxx", "name": "Review", "params": undefined, "path": undefined}
How can I get the params to pass onto the review screen properly?
here is the working code see it!
App.js
import * as React from 'react';
import { Button, View, Text, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details',{ title:"Full Stack Developer"})}
/>
</View>
);
}
function DetailsScreen({ navigation, route }) {
const { title } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>{title}</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
I had not properly installed the #react-navigation/native and #react-navigation/stack dependencies. Find them stated here and here respectively.
i am trying to pass value from login and register into dashbord since sign is a unique compont i dont know how to pass log from login and register can someone help
sign.js
export default function Sign({navigation}) {
async function onGoogleButtonPress() {
await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();
setuserInfo(userInfo);
navigation.navigate('dash', {userInfo});
}
return (
<View style={styles.prheight}>
<View style={styles.buttonw}>
<GoogleSigninButton
style={{width: 192, height: 48}}
size={GoogleSigninButton.Size.Wide}
color={GoogleSigninButton.Color.Light}
onPress={onGoogleButtonPress}
// disabled={this.state.isSigninInProgress}
/>
</View>
</View>
);
}
register.js
export default function Register(props) {
return (
<View style={styles.prheight}>
<View style={styles.buttonw}>
<Sign navigation={props.navigation} log={name:"register"} />
</View>
</View>
);
}
login
export default function login(props) {
return (
<View style={styles.prheight}>
<View style={styles.buttonw}>
<Sign navigation={props.navigation} log={name:"login"} />
</View>
</View>
dash.js
export default function dash(props) {
const [text, setTextbaby] = useState();
const {userInfo} = props?.route?.params;
console.log(props.log);
You should pass log prop in Sign component and take it like this.
export default function Sign({ navigation, log }) {
async function onGoogleButtonPress() {
await GoogleSignin.hasPlayServices();
const userInfo = await GoogleSignin.signIn();
setuserInfo(userInfo);
navigation.navigate('dash', {userInfo, log});
}
// some code
}
after all, log will be located inside props.route.params object
export default function dash(props) {
const [text, setTextbaby] = useState();
const {userInfo, log} = props?.route?.params;
console.log(log);
}
UPDATED: use double brackets (in order to pass object)
log={{name: "register"}}
log={{name: "login"}}
we can pass a value from one screen to another screen through async-storage react-navigation or declare a value globally.
To pass a value from login to dashboard I recommend you to see this async-storage Docs https://react-native-async-storage.github.io/async-storage/docs/install
async-storage store a value in App while React navigation does not store a value in App, React navigation just transfer value from one screen to another.
react navigation Docs https://reactnavigation.org/docs/navigating/
passing a value from one component to another
import { Text, View, Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId } = route.params;
const { otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() =>
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}```
I have few questions about React Navigation. I want to navigate from child screen to parent's sibling component, but I couldn't find a proper way for that. My navigation in the app looks like this:
Stack (Main)
LoginPage
Desk (DrawerNavigation)
Messages
MyAccount
Here I want to navigate to MyAccount, from Messages (Desk's child screen). How can I achieve that?
I'm using #react-navigation/stack, #react-navigation/drawer to config and useNavigation to redirect screen:
import * as React from "react";
import { Button, Text, View } from "react-native";
import { NavigationContainer, useNavigation } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import { createDrawerNavigator } from "#react-navigation/drawer";
const STYLE = {
flex: 1,
alignItems: "center",
justifyContent: "center",
width: "100%",
};
function LoginPage() {
const navigation = useNavigation();
return (
<View style={STYLE}>
<Text>LoginPage</Text>
<Button
title="Go to DrawerNav"
onPress={() => navigation.navigate("Desk")}
/>
</View>
);
}
function Messages() {
const navigation = useNavigation();
return (
<View style={STYLE}>
<Text>Messages</Text>
<Button
title="Go to MyAccount"
onPress={() => navigation.navigate("MyAccount")}
/>
</View>
);
}
function MyAccount() {
return (
<View style={STYLE}>
<Text>MyAccount</Text>
</View>
);
}
const Drawer = createDrawerNavigator();
const Desk = () => {
return (
<Drawer.Navigator initialRouteName="Messages">
<Drawer.Screen name="Messages" component={Messages} />
</Drawer.Navigator>
);
};
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="LoginPage">
<Stack.Screen name="LoginPage" component={LoginPage} />
<Stack.Screen
name="Desk"
component={Desk}
options={{ headerShown: false }}
/>
<Stack.Screen name="MyAccount" component={MyAccount} />
</Stack.Navigator>
</NavigationContainer>
);
}
I am do do navigation in react native where all the back arrow or back press return to initial route. On last on option is to list to onBackPreessed event and passs call to init route which is home.
I am hoping their will be props for allowing the Screen to return to init Screen in stack navigations
What is happening
On home:
go details then go A
back arrow press in A, it return back to details
Need actions
On home:
go details then go A
back arrow press in A return back to home instead of details
The code I try
import * as React from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to A"
onPress={() => navigation.navigate('A')}
/>
</View>
);
}
function A({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>AAAAAAAAAAAAAAAAAAA Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home" detachInactiveScreens={true}
detachPreviousScreen={true}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Group screenOptions={{ presentation: 'modal' }}>
<Stack.Screen name="Details" component={DetailsScreen}
options={{ presentation: 'transparentModal' }}
/>
<Stack.Screen name="A" component={A} />
</Stack.Group>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
u can do it by passing "key" to "navigate"
more info (source):
https://reactnavigation.org/docs/navigation-prop/
https://reactnavigation.org/docs/navigation-prop/#going-back-from-a-specific-screen
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_A });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_B });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_C });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_D });
navigation.navigate({ key: SCREEN_KEY_A }); // will go to screen A FROM screen D
I think you can use BackHandler on Screen A.
So you should listen for BackHandler in Screen A and the navigate to Home screen when it's triggered.
Your Screen A should look like this:
import { BackHandler } from 'react-native';
function handleBackPressHandler() {
navigation.navigate('HomeScreen');
return true;
}
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleBackPressHandler);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleBackPressHandler);
};
}, []);
The default behaviour of React Navigation is this only, it takes you to the last visited stack on pressing back but if you want to update it, you can you this line of code:
useFocusEffect( //imported from #react-navigation/native-stack
React.useCallback(() => {
const onBackPress = () => {
navigation.navigate('InitialRouteName');
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () =>
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
}, [])
);
For reference, you can check this out - https://reactnavigation.org/docs/custom-android-back-button-handling/
please try this,
import { BackHandler } from 'react-native';
<!- -->
useEffect(() => {
const backAction = () => {
navigation.navigate('intialRouteName');
return true;
};
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
backAction,
);
return () => backHandler.remove();
}, []);
I have four components A,B,C,D. Each of these components have its local state.
These are stacked using react stack navigations
Now i like to pass on each of the local states in A, B and C to the last component D.
I do not need to give routes. I already have routes onPress using prop.navigation.navigate, that takes me from A to B to C to D.
I just need to pass state of A directly to D, B to D and C to D?
Thanks
sal
Final Output:
Here is how you can pass the states from A, B, C to D.
You just need to pass the state of the parent as a parameter to the next Screen route while navigating to it, then you can access those parameters with the help of route.
import React, { useState } from 'react';
import { Button, View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function A({ navigation }) {
const [fromA, setFromA] = useState('From A');
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>A Screen</Text>
<Button
title="Go to B"
onPress={() => navigation.navigate('B', { fromA: fromA })}
/>
</View>
);
}
function B({ navigation, route }) {
const [fromB, setFromB] = useState('From B');
const { fromA } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>A Screen</Text>
<Button
title="Go to C"
onPress={() => navigation.navigate('C', { fromA: fromA, fromB: fromB })}
/>
</View>
);
}
function C({ navigation, route }) {
const [fromC, setFromC] = useState('From C');
const { fromA, fromB } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>A Screen</Text>
<Button
title="Go to D"
onPress={() =>
navigation.navigate('D', { fromA: fromA, fromB: fromB, fromC: fromC })
}
/>
</View>
);
}
function D({ navigation, route }) {
const { fromA, fromB, fromC } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>D Screen</Text>
<Text>From Screen A: {fromA}</Text>
<Text>From Screen B: {fromB}</Text>
<Text>From Screen C: {fromC}</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="A">
<Stack.Screen name="A" component={A} />
<Stack.Screen name="B" component={B} />
<Stack.Screen name="C" component={C} />
<Stack.Screen name="D" component={D} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Live App Example on Expo Snack
You can read the full documentation here: Passing parameters to routes