'OnPress' non functional used in ternary operator - react-native

I am new to React Native. I am trying to render a button conditional on the value of a 'global' value. This is incredibly frustrating.
Normally it would be a simple case of using an 'if/else' statement to accomplish this in Javascript or nearly any other language. Apparently this is not possible in React Native. Here is my code:
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 }) {
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="Do Stuff"> onPress={() => navigation.navigate('Stuff')} </Button>)}
</>
);
}
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="Stuff" component={StuffScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
This code above correctly renders a 'Home' screen with a button that reads 'Go to Login' as it should. However the 'OnPress' statement attached to the button is not functional...nothing happens when pressing the button on the phone. If I were to simply insert a button with the 'OnPress' assigned singly, without the ternary operator statement, I can get the button to be functional.
Can somebody please explain why the 'OnPress' is not functioning when the button is used within a ternary operator? In addition would I be able to change the value of 'isLogged' in another function (for example the 'Login') and have this correctly pass to the 'Home' screen?
Why are simple tasks that could be handled with 'if/else' statements so challenging in React Native? This is driving me crazy...I thank you in advance.

The way you are providing the onpress is wrong. You are providing it as a child but it should be a prop like below.
{isLogged === 0 ? (
<Button
title="Go to Login"
onPress={() => navigation.navigate('Login')}
/>
) : (
<Button
title="Do Stuff"
onPress={() => navigation.navigate('Stuff')} />
)
}

Related

React DrawerNavigation Is Not Working (Nothing Happens) While I Drag To Open Side Menu

I'm trying to introduce DrawerNavigation under StackNavigation. My StackNavigation is working fine. But when I'm dragging the screen DrawerNavigation is not working. Nothing happens...No errors also.
I am using TouchableOpacity for the list items. Though I don't think so, is there any chance it is occurring due to the first touch on list-item??? If not, then can anyone point me out what the issue is? I really appreciate any help you can provide.
I have given my Navigator.Js code here and a video Url to understand better what is happening for my case.
Video URL - https://drive.google.com/file/d/1MhD3gB8Pp4tqbXr1HktOPa-2xOqW0xoA/view?usp=sharing
Instead of wrapping DrawerNavigator inside StackNavigator, wrap your StackNavigator inside DrawerNavigator.
Working Example: Expo Snack
Output:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const StackNav = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={() => <Text>Login</Text>} />
<Stack.Screen name="Register" component={() => <Text>Register</Text>} />
</Stack.Navigator>
);
};
export default function App() {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Stack" component={StackNav} />
<Drawer.Screen
name="HomeNews"
component={() => (
<View style={styles.container}>
<Text>HomeNews</Text>
</View>
)}
/>
<Drawer.Screen
name="StateNews"
component={() => (
<View style={styles.container}>
<Text>StateNews</Text>
</View>
)}
/>
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});

React Native Buttons onPress nothing happens, also onChangeText not working

I am new to React Native. I have a single login form with two fields. I want to authenticate the user before sending him to Dashboard.js. No matter what I try the button is not doing anything(absolutely nothing happens,no error). I have kept the code in Login.js to show all the things I have tried to do namely
routing to dashboard.js
trying to do something with invoking the handleSubmitPress function on button press.
pop an alert.
I have used two buttons. One from react-native-paper and one from react-native.
I am giving the code of my app.js and login.js below. Please can someone help?
CODE
App.js
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import DashBoard from "./mainmenu/DashBoard";
import Login from "./mainmenu/Login";
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="DashBoard" component={DashBoard} />
</Stack.Navigator>
</NavigationContainer>
);
}
Login.js
import React, { useState } from "react";
import { Title, TextInput} from "react-native-paper";
import { View, Alert,Button } from "react-native";
export default function Login() {
const [mobile, setMobile] = useState("123456789");
const [password, setPassword] = useState("123");
function handleSubmitPress() {
console.log({ mobile, password });
}
return (
<View
style={{
backgroundColor: "skyblue",
alignItems: "center",
justifyContent: "center",
}}
>
<TextInput
label="Your mobile number "
value={mobile}
onChangeText={(text) => setMobile(text)}
/>
<TextInput
label="Type Password "
value={password}
onChangeText={(text) => setPassword(text)}
/>
<Button
icon="camera"
type="submit"
mode="contained"
//onPress={() => props.navigation.navigate("DashBoard")}
onPress={()=>Alert.alert('Navigate pressed')}
>
Navigate
</Button>
<Button
title="Print"
onPress={() => Alert.alert('Simple Button pressed')}
// onPress={handleSubmitPress()}
/>
</View>
);
}
Change your Login component to this.
...
const Login = ({navigation}) => {
const [mobile, setMobile] = useState('123456789');
const [password, setPassword] = useState('123');
function handleSubmitPress() {
console.log({mobile, password});
}
return (
<View
style={{
backgroundColor: 'skyblue',
alignItems: 'center',
justifyContent: 'center',
}}>
<TextInput
label="Your mobile number "
value={mobile}
onChangeText={text => setMobile(text)}
/>
<TextInput
label="Type Password "
value={password}
onChangeText={text => setPassword(text)}
/>
<Button
title="title"
icon="camera"
type="submit"
mode="contained"
onPress={() => navigation.navigate('DashBoard')}>
Navigate
</Button>
<Button title="Print" onPress={() => handleSubmitPress()} />
</View>
);
};
export default App;
There were a couple problems.
I've used the default React Native buttons. So I added a title prop to one of the buttons, because that's required. I gave it the value "title", but change this to what you want or use the React Native Paper buttons.
The main problem was how you called handleSubmitPress in your button onPress.
Your onChangeText was fine, you just couldn't see the result, because the handleSubmitPress wasn't being called.
I've also used destructuring so you're able to access the navigation prop directly. You can also do const Long = (props) => {...} and use props.navigation, but either way you need to pass in something otherwise navigation will not work.

Change variable values across functions like a global variable in React Native?

I am new to React Native and I am trying to change a variable set in one function from another function. This should be similar to changing a 'global' variable to a new value. Here is my code:
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 }) {
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 title="Do Stuff" onPress={() => navigation.navigate('Stuff')} />
)}
</>
);
}
function LoginScreen({ navigation }) {
//do login stuff here...
{isLogged => setLog(1)} //unable to change 'isLogged' to a value of '1'...?
}
function StuffScreen({ navigation }) {
//do some stuff 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="Stuff" component={StuffScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
The error I get makes it obvious the 'isLogged' variable is not recognized in the function 'LoginScreen'. What is the proper way to use and manipulate 'global' variables that can be changed across various functions in React Native? I thank you in advance for any suggestions.
Looking into a suggestion`from another user it seems the 'global' is what I need, however I am still having difficulties. Here is some adjusted code:
var func = require('./global');
global.config = func(0);
function HomeScreen({ navigation }) {
var _status = global.config;
return (
<>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Passed config: {JSON.stringify(_status)}</Text>
<Text>Home Screen</Text>
</View>
{_status === 0 ? (
<Button
title="Go to Login"
onPress={() => navigation.navigate('Login')}
/>
) : (
<Button title="BroadCast" onPress={() => navigation.navigate('BroadCast')} />
)}
</>
);
}
function LoginScreen({ navigation }) {
//do login stuff here...
global.config = func(1); //new value of "1" does not pass to 'HomeScreen'
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Login Screen</Text>
<Text>Set Global: {JSON.stringify(global.config)}</Text> //indicates '0'...WHY?????
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
</View>
);
}
Here is the 'global' file where I attempt to load from external .js file:
module.exports = function(variable) {
console.log(variable);
return variable;
}
My problem here is that 'global.config' that I attempt to change in the 'LoginScreen' function does not display the updated value when returning to 'Home' screen. WHY...???? I cannot believe such a simple concept in any other language I know is nearly impossible in React Native...this is far more complicated than it should be...any advice on what I am not understanding is GREATLY appreciated...this is killing me.

Basic simple React Navigation v5 navigating between screens

I've spent 2 days search, reading and find lots of v3 and v4 class based examples for how to handle navigation in React Native Navigation.
All I want to achieve is to move between 2 of my screens using react native navigation. My App.js contains the Tab navigator and that works fine. The tab opens up a component (screen) called Mens and from there I want to be able to open up a PDP page that passes in properties of an article ID.
I have tried numerous ways of wiring up the application to allow this; I've read all the react native documentation and tried a number of approaches;
Created a seperate file to include the naviagtion stack;
import * as React from 'react'
import { NavigationContainer } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
import News from './news';
import Mens from './mens'
import Watch from './watch'
const Stack = createStackNavigator()
function MainStackNavigator() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="News" component={News} />
<Stack.Screen name="Mens" component={Mens} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default MainStackNavigator
But when I try to use one of the screens, I get an error. The onpress I try is;
<TouchableOpacity onPress={() => navigation.navigate('Mens')}>
I have also tried to move the NavigationContainer / Stack Navigator code into the News component, but I haven't manage to make that work.
The flow that I want is simple enough; App.js has my tabs, 5 tabs that navigate to the main screens and then on each of those, people can click on a list item in a flat list (which displays a summary) to read the full article.
The news.js file content is below;
import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Image, ListItem, Text, View, StyleSheet, ScrollView, TouchableOpacity, Alert} from 'react-native';
import Moment from 'moment';
import MatchReports from './matchreports.js';
import navigation from '#react-navigation/native';
const News = (props) => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
function chkValue(val) {
if(val.length == 0){
val = 'https://derbyfutsal.files.wordpress.com/2019/07/banner-600x300.png';
}else{
val = val;
}
return val;
}
useEffect(() => {
fetch('https://xxxx')
.then((response) => response.json())
.then((json) => {
setData(json)
})
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<ScrollView>
<View style={styles.body}>
<Text style={styles.titlesnopadding}>Watch</Text>
<View style={{height:200}}>
<Watch />
</View>
<Text style={styles.titles}>Match reports</Text>
<View style={{height:100}}>
<MatchReports typeOfProfile='Men'/>
</View>
<Text style={styles.titles}>Latest News</Text>
{isLoading ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<View>
<TouchableOpacity onPress={() => navigation.navigate('Mens')}>
<Image style={styles.img} source={{ uri: chkValue(item.jetpack_featured_media_url) }} />
<View>
<Text style={styles.textbck}>{item.title.rendered.replace(/<\/?[^>]+(>|$)/g, "")}</Text>
<Text style={styles.summary}>{item.excerpt.rendered.replace(/<\/?[^>]+(>|$)/g, "")}{"\n"}{Moment(item.date, "YYYYMMDD").fromNow()}</Text>
</View>
</TouchableOpacity>
</View>
)}
/>
)}
</View>
</ScrollView>
);
};
Any help is appreciated, as I've read so many using class instead of functional programming and out of date navigation that it's been challenging working it out.
EDIT:
I had missed the props.navigation.navigate('Mens'), which works fine now. Though its only half solves my problem.
I have the following inside my app.js;
import 'react-native-gesture-handler';
import React from 'react';
import { View, StyleSheet, Image } from 'react-native';
import News from './components/news';
import Shop from './components/shop';
import Mens from './components/mens';
import Fixtures from './components/fixtures';
import Ladies from './components/ladies';
import Pdp from './components/pdp'
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
const App = () => {
return (
<View style={styles.header}>
<View>
</View>
<View style={styles.body}>
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="News" component={News} />
<Tab.Screen name="Mens" component={Mens} />
<Tab.Screen
name="icon"
component={Shop}
options={{
title: '',
tabBarIcon: ({size,focused,color}) => {
return (
<Image
style={{ marginTop:20,width: 80, height: 80 }}
source={{
uri:
'https://derbyfutsal.files.wordpress.com/2020/05/derby-futsal-logo-2019.png',
}}
/>
);
},
}}
/>
<Tab.Screen name="Ladies" component={Ladies} />
<Tab.Screen name="Fixtures" component={Fixtures} />
</Tab.Navigator>
</NavigationContainer>
</View>
</View>
)
};
const styles = StyleSheet.create({
header: {
marginTop: 20,
height:0,
flex: 1
},
body: {
flex:2,
flexGrow:2,
},
nav: {
fontSize: 20,
},
});
export default App;
Anything thats been set as tab Screen in this works just fine if I reference it in my news.js screen, but I don't want to declare PDP.js in this as I don't want it to display as a tab.
Instead once a user has gone to a screen using the tab navigation, the user then clicks on a item in the flatlist and it opens up pdp.js.
In many ways, once someone has opened up the main categories (as seen on the tab navigation) and clicked on an item in the flatlist, all I want to do is;
<a href="pdp.js?id=xxxxx">
https://reactnavigation.org/docs/navigation-actions/#navigate
import { CommonActions } from '#react-navigation/native';
navigation.dispatch(
CommonActions.navigate({
name: 'Profile',
params: {
user: 'jane', // props.route.params.user
},
})
);

Navigation back click event in React Native

I am working on a React Native application. I am using navigation in my application. I want to do something when user presses back navigation i.e. moved to a back screen.
How can i get the click event of "blacked circle Frage" in the above image. I am working on IOS
Use a custom header with
import { Header } from "native-base";
And add below code in your route file to disable default header.
navigationOptions: {
header: null
}
my custome header code for your reference
<Header style={styles.header}>
<View style={{ flex: 2 }}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => { this.createNote(); this.props.navigation.navigate('Home') }}>
<Icon name="arrow-back" size={28} color="#606060" />
</TouchableOpacity>
</View>
<View style={{ flex: 8 }}></View>
<View style={{ flex: 2 }}>
<TouchableOpacity
style={styles.iconButton}
onPress={() => { this.createNote(); this.props.navigation.navigate('Home') }}>
<Icon name="check" size={28} color="#606060" />
</TouchableOpacity>
</View>
</Header>
reference link:- https://www.npmjs.com/package/native-base
It probably varies depending on the libraries you are using. I am using react-native-paper in Expo, which uses the headerLeft option in the Stack.Screen component. Here's a complete example - save it and then 'expo start'
import { Provider as PaperProvider, Text } from 'react-native-paper'
import { NavigationContainer } from '#react-navigation/native'
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<PaperProvider>
<NavigationContainer >
<Stack.Navigator>
<Stack.Screen
name="Example"
options={{
title: 'Example',
headerLeft: () => <Text>Custom left button</Text>,
}}
component={() => <Text>Example body text</Text>}
/>
</Stack.Navigator>
</NavigationContainer>
</PaperProvider>
)
}
You can use onPress={() => this.props.navigation.goBack()} on TouchableOpacity if you are redirecting to the previous page
Also you can use this.props.navigation.navigate('Any_Screen') to move to other screens.
Also, I would like to suggest you to get familiar with BackHandler to move back to previous page when hardware back button is pressed.
add the code
onClick={this.props.navigation.goBack()}
or use specif navigation replace go back to
onClick={this.props.navigation.navigate('namepagespacific')}
check this screen there are mutiple example of handling click event
import React from 'react';
import { View, Text, StyleSheet, Button} from 'react-native';
class DetailsScreen extends React.Component {
static navigationOptions = ({ navigation, navigationOptions, screenProps }) => {
return {
title: navigation.getParam('title', 'A Nested Details Screen'),
};
};
render() {
const { navigation } = this.props;
const itemId = navigation.getParam('itemId', 'NO-ID');
const otherParam = navigation.getParam('otherParam', 'some default value');
return (
<View style={styles.detailsScreen}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() => this.props.navigation.push('Details')}
/>
<Button
title="Go to Home"
onPress={() => this.props.navigation.navigate('Home')}
/>
<Button
title="Go back"
onPress={() => this.props.navigation.popToTop()}
/>
<Button
title="Update the title"
onPress={() => this.props.navigation.setParams({ title: 'Updated!' })}
/>
<Button
title="Modal"
onPress={() => this.props.navigation.navigate('MyModal')}
/>
</View>
);
}
}
const styles = StyleSheet.create({
detailsScreen: {
flex: 1,
alignItems: "center",
justifyContent: "center"
}
})
export default DetailsScreen;
things you have asked in the comment section I could not find any exact answer for your question but you can take a look into this url how header buttons work
https://snack.expo.io/#react-navigation/simple-header-button-v3
hope this will work for you
header: ({ goBack }) => ({
left: ( <Icon name={'chevron-left'} onPress={ () => { goBack() } } /> ),
}),
you can also follow this page https://github.com/react-navigation/react-navigation/issues/779