Change variable values across functions like a global variable in React Native? - 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.

Related

Expo navigation Drawer doesnt open , what can i do to solve this?

Issue :
Side bar doesnt open when i press the bars icon near navigation Header and i dont recieve any error messages in console.
the bars icon is supposed to trigger a drawer sliding from the left when pressed on.
Code :
import * as React from "react";
import { Button, View } from "react-native";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { NavigationContainer } from "#react-navigation/native";
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Button
onPress={() => navigation.navigate("Notifications")}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
I'm using expo and came across the same issue, "react-native-reanimated" is added as part of drawer navigation setup ( https://reactnavigation.org/docs/drawer-navigator/) and adding the relevant plugin into the babel.config.js resolved the issue e.g., plugins: ["nativewind/babel", "react-native-reanimated/plugin"]

How to define routes in React Native without displaying them in a navigator?

I have a bottom tab navigator made with React Navigation on a basic React Native app. It only gives access to 4 screens. Some screens may contains buttons that would open a new page (for example: a user profile page). How to define the route without displaying it in the bottom tab navigator?
The code:
const Tab = createBottomTabNavigator();
export default function Router() {
const { t } = useTranslation();
return (
<Tab.Navigator initialRouteName={screen.home}>
<Tab.Screen name={screen.home} component={Home}/>
<Tab.Screen name={screen.a} component={A}/>
<Tab.Screen name={screen.b} component={B}/>
<Tab.Screen name={screen.c} component={C}/>
</Tab.Navigator>
);
}
The idea would be to allow a click like that:
function ScreenB(){
const navigation = useNavigation();
return (
<TouchableOpacity onPress={() => navigation.navigate("/user/123")}>
<Text>see user 123</Text>
</TouchableOpacity>
)
}
Thanks for your help!
Online example https://snack.expo.io/#vasylnahuliak/great-bubblegum
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const HomeScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home screen</Text>
</View>
);
};
const ProfileScreen = ({ navigation }) => {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
};
const DetailsScreen = () => { // <--- Screen without navigation header
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details screen</Text>
</View>
);
};
const ProfileStack = createStackNavigator();
const ProfileStackScreen = () => {
return (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Settings" component={ProfileScreen} />
</ProfileStack.Navigator>
);
};
const MainTab = createBottomTabNavigator();
const MainTabs = () => {
return (
<MainTab.Navigator>
<MainTab.Screen name="Home" component={HomeScreen} />
<MainTab.Screen name="Profile" component={ProfileStackScreen} />
</MainTab.Navigator>
);
};
const RootStack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="MainTabs"
component={MainTabs}
options={{ headerShown: false }}
/>
<RootStack.Screen name="Details" component={DetailsScreen} /> // <--- Screen without navigation header
</RootStack.Navigator>
</NavigationContainer>
);
}
Official documentation: https://reactnavigation.org/docs/hiding-tabbar-in-screens

Unable to navigate to new screen react native getting an error undefined Object navigate.navigation

Unable to navigate to new screen react native getting an error:
TypeError: undefined is not an object (evaluating 'navigation.navigate')
Can someone explain where I go wrong?
Below is the code I'm using.
const MessagesScreen = ({navigation}) => {
return (
<Container>
<FlatList
data={Messages}
keyExtractor={item=>item.id}
renderItem={({item}) => (
<Card onPress={() => navigation.navigate('Chat', {userName: item.userName})}>
<UserInfo>
<UserImgWrapper>
<UserImg source={item.userImg} />
</UserImgWrapper>
<TextSection>
<UserInfoText>
<UserName>{item.userName}</UserName>
<PostTime>{item.messageTime}</PostTime>
</UserInfoText>
<MessageText>{item.messageText}</MessageText>
</TextSection>
</UserInfo>
</Card>
)}
/>
</Container>
);
};
export default MessagesScreen;
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
});
it's seem that you forget to declare your screen in Navigator stack. something like this
<Stack.Screen
name="MessagesScreen"
component={MessagesScreen} />
this is an example from official page with
react navigation v5
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;

Navigation Container not showing without <ScrollView>

I'm a React Native student. I'm sorry if this is a basic issue.
I have only one component in my project that is called Main - this component is imported in App.js. (Important: I removed all styles in App.js already)
So - here's my code in Main.JS.
import * as React from 'react';
import { Text, View } from 'react-native';
import { Ionicons } from '#expo/vector-icons';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { NavigationContainer } from '#react-navigation/native';
import Search from '../Search'
import ClientsRegister from '../ClientRegister'
import { ScrollView } from 'react-native-gesture-handler';
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home!</Text>
</View>
);
}
function SettingsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings!</Text>
</View>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<ScrollView>
<NavigationContainer>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let iconName;
if (route.name === 'Home') {
iconName = focused ? 'ios-information-circle' : 'ios-information-circle-outline';
} else if (route.name === 'Settings') {
iconName = focused ? 'ios-list-box' : 'ios-list';
}
// You can return any component that you like here!
return <Ionicons name={iconName} size={size} color={color} />;
},
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>
</ScrollView>
);
}
See the <ScrollView>? Of course - that's not the right thing to do. But If I use <View> only - the navigation bar disappears.
So - here are both cases for you. I Think it will be really gigantic here... but here are the prints.
With <ScrollView>
With <View>
What am I doing wrong here? I Need to use the VIEW, of course, but it's not appearing. Oh, for the case it was hiding at the bottom, behind the control buttons, I tried to put <View style={{marginBottom:100}}> but didn't work either.
(I really need to charge my phone, don't I?)
Hello similar to what #Meyer Buaharon said - to fix this you need to change:
<View>
<NavigationContainer>
...
</NavigationContainer>
</View>
To:
<View style={{flex: 1}}>
<NavigationContainer>
...
</NavigationContainer>
</View>
This means the View fills the entire screen.
I had a similar problem that the scroll view show the content and the view doesn't
<View style={{flex:'1'}}>
...
</View>
Hope this solves it
Maaaan....
Idk why but I moved the code directly to App.js instead doing it in Main.js and importing.
Now it's working.
I really hate life sometimes. (Just kidding...don't really hate life)

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