react-native: How to hide an element in createStackNavigator [closed] - react-native

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a stackNavigator is displayed in my menu with my configuration
const ProfileStack = createStackNavigator();
function ProfileNavigator() {
return (
<ProfileStack.Navigator
drawerStyle={{ width: '100%', color: 'red' }} // not work
>
<ProfileStack.Screen
name="ProfileScreen"
component={ProfileScreen}
options={{
headerBackTitleVisible: false, // not work
headerMode: 'none',
headerShown: true // work
}}
/>
</ProfileStack.Navigator>
)
}
( I have profile in menu ( red border ) and button profile ( icon )
And i want to keep the button, hide in the menu and keep the header in the webpage/view.
I try many conf with the documentation ( https://reactnavigation.org/docs/4.x/stack-navigator-1.0#navigationoptions-for-screens-inside-of-the-navigator )
I would like hide the element of the menu. Because the page/view is accessible from a button.
I check many configurations of createStackNavigator.
headerBackTitleVisible and others didn't work.
Do you know how to hide an element bevcause i'm lost :( ?
thanks

Take a look at this React Navigation Github issue. The person who posted that wanted to hide an item in the drawer menu, but still be able to access the drawer from that page. The following workaround was provided:
I found the following workaround :
Create a component returning null
Pass the component to the drawerLabel navigationOptions of the screen you want the item to be hidden
Hope this helps.
Here is an example below, which you can copy, paste, and run if you would like:
App.js:
import React from 'react';
import TestAppContainer from "./TestAppContainer";
export default function App() {
return (
<TestAppContainer/>
);
}
TestAppContainer.js:
import React from "react";
import {NavigationContainer} from "#react-navigation/native";
import {DrawerNavigatorTest} from "./NavigatorTest";
const TestAppContainer = props => {
return (
<NavigationContainer>
<DrawerNavigatorTest />
</NavigationContainer>
);
}
export default TestAppContainer;
NavigatorTest.js:
import React from "react";
import {createDrawerNavigator} from "#react-navigation/drawer";
import TestScreen from "./TestScreen";
import TestScreenTwo from "./TestScreenTwo";
import NullComponent from "./NullComponent";
const TestDrawerNavigator = createDrawerNavigator();
export const DrawerNavigatorTest = () => {
return(
<TestDrawerNavigator.Navigator drawerContentOptions={{activeBackgroundColor: "transparent"}}>
<TestDrawerNavigator.Screen name={"Test"} component={TestScreen} />
<TestDrawerNavigator.Screen name={"Test2"} component={TestScreenTwo} options={{drawerLabel: NullComponent}}/>
</TestDrawerNavigator.Navigator>
);
}
NullComponent.js:
import React from "react";
const NullComponent = props => {
return null;
}
export default NullComponent;
TestScreen.js:
import React from "react";
import {SafeAreaView, View, Text, Button} from "react-native";
const TestScreen = props => {
const buttonPressHandler = () => {
props.navigation.navigate("Test2");
};
return (
<SafeAreaView style={{flex: 1,}}>
<View style={{flex: 1, alignItems: "center", justifyContent: "center"}}>
<Text>Test Screen</Text>
<Button title={"Go to next screen."} onPress={buttonPressHandler} />
</View>
</SafeAreaView>
);
};
export default TestScreen;
TestScreenTwo.js:
import React from "react";
import {SafeAreaView, View, Text} from "react-native";
const TestScreenTwo = props => {
return (
<SafeAreaView style={{flex: 1,}}>
<View style={{flex: 1, alignItems: "center", justifyContent: "center"}}>
<Text>Test Screen Two</Text>
</View>
</SafeAreaView>
);
};
export default TestScreenTwo;
Note that this is not a perfect solution, but a workaround. It could use some more fine tuning. You may also want to look into custom drawer components. I'm not very familiar with custom drawer components, but you may be able to get cleaner functionality with custom drawer items. See the React Navigation Docs.

Related

Error: Couldn't find a navigation object. Is your component inside NavigationContainer?

I am trying to navigate from my login screen to the home screen using a pressable button. However, the code that I now have gives the following error: Couldn't find a navigation object. Is your component inside NavigationContainer?. The error is aimed on row 8 (const navigation = useNavigation();).
LoginButton.js:
import React, { Component } from "react";
import { View, Text, Image, Pressable, Button } from "react-native";
import { useNavigation } from "#react-navigation/native";
import styles from "./styles";
import HomeScreen from "../../screens/Home";
const LoginButton = () => {
const navigation = useNavigation();
return (
<View style={styles.container}>
<Pressable
onPress={() => navigation.navigate("Home")}
style={styles.button}
>
<Text style={styles.buttontext}>Login</Text>
</Pressable>
</View>
);
};
export default LoginButton;
The LoginButton is inserted as a component in the LoginItem inside the last <View. LoginItem.js:
import React from "react";
import { View, Text, Image } from "react-native";
import styles from "./styles";
import LoginButton from "../LoginButton";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
const Stack = createNativeStackNavigator();
const LoginItem = (props) => {
return (
<View style={styles.logincontainer}>
{/* Background image of the login screen */}
<Image
source={require("../../../assets/images/blue-sky-start-screen.jpg")}
style={styles.loginbackground}
blurRadius={4}
></Image>
{/* Title of the login screen */}
<View style={styles.titlecontainer}>
<Text style={styles.companytitle}>BestelSnel</Text>
</View>
{/* Login button */}
<View style={styles.loginbutton}>
<LoginButton></LoginButton>
</View>
</View>
);
};
export default LoginItem;
useNavigation only works if your component is inside of a NavigationContainer and a Navigator like mentioned on the getting-started-page:
https://reactnavigation.org/docs/hello-react-navigation
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
HomeScreen would be your LoginItem
In my case, I got this error because autocomplete added the wrong import statement.
import { useNavigation } from "#react-navigation/core";
but the one I needed is:
import { useNavigation } from "#react-navigation/native";
Hope this helps anybody to save some minutes.
I had this issue as well, and the accepted answer did not work for me.
What I did get working on was importing the component I wanted to go to and using that in the navigate() call. Generally, this probably means just removing the quotes so your param to that function is a Component and not a String.
Given the code from the question, the code would be:
onPress={() => navigation.navigate(Home)}
Very similar to the original, just minus the quotes, as mentioned.
I was passing the params correctly also, but params had a react component in it. That's why it was giving this error.
// product should not have a react component
props.navigation.navigate(ROUTE_TEST, {product});

I want to move the screen with a button in React Native

I want to go to another screen by pressing the image button on the screen, but I don't know how. I am a complete beginner.
How can I go to the next page?
import React, { Component } from 'react'
import { StyleSheet, Text, View, TouchableOpacity,Image,Alert } from 'react-native';
import {} from 'react-navigation';
const ButtonScreen = props => {
const content = (
<View style= {[styles.button]}>
<Image source={require('../assets/icon/룰렛.png')} style={{
transform: [{scale: 0.37}],
}}
/>
</View>
)
return (
<TouchableOpacity onPress={() => {
Alert.alert('빨리');
}}
>{content}</TouchableOpacity>
)
}
const styles = StyleSheet.create ({
button: {
top: 60,
flexDirection: 'row',
alignItems: 'center',
height: '30%',
width: '100%',
},
})
export default ButtonScreen;
for navigation in react-native there are various libraries. react-navigation, react-native-router-flux, react-native-navigation(wix) are the ways you can use for navigation.
react-navigation is the famous one that currently has V5.x following by thorough documentation. It uses JavaScript codes for navigation and I assume you installed this library.
the react-native-router-flux use react-navigation V4.x and it really looks like react-router-dom in React-js. However I strongly suggest to not using that due to problems regarding performance.
react-native-navigation(wix) has the highest performance because it uses native codes for navigation. however it has poor document and it is really difficult for beginners to use.
In order to use the current version of react-navigation the first step you need to do is the installation of requirement then you need to have separate file for defining your routes. Lets assume you have two screens. the file looks like the following code:
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import Screen1 from 'the path of Screen1'
import Screen2 from ' the path of Screen2'
const Stack = createStackNavigator();
function Navigation() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Screen1" component={Screen1} />
<Stack.Screen name="Screen2" component={Screen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default Navigation
then you need to import this file on your index file.
import Navigation from "the path of Navigation";
AppRegistry.registerComponent(appName, () => Navigation);
if you are at ButtonScreen and you want to go on Screen2 you need the following code:
import React, { Component } from 'react'
import { StyleSheet, Text, View, TouchableOpacity,Image,Alert } from 'react-native';
const ButtonScreen = props => {
const content = (
<View style= {[styles.button]}>
<Image source={require('../assets/icon/룰렛.png')} style={{
transform: [{scale: 0.37}],
}}
/>
</View>
)
return (
<TouchableOpacity onPress={() => props.navigation.navigate("Screen2")}
>{content}</TouchableOpacity>
)
}
const styles = StyleSheet.create ({
button: {
top: 60,
flexDirection: 'row',
alignItems: 'center',
height: '30%',
width: '100%',
},
})
export default ButtonScreen;
this is the easiest way to navigate and I recommend you to read the document

TouchableRipple onPress is not working with react navigation

I am using stack navigator in my app to navigate through different components. but here I am facing 2 different issues. issue (1) I used a switch to toggle between dark and light theme, in the module, it works fine when using onPress but when called through stack screen it is not working. issue (2) I wanted to give some space between header text and the switch button but every time I add some padding to switch component, it is also applied to the header text. How can I solve these issues?
Here is App.js Component code:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow strict-local
*/
import React from 'react';
import {StatusBar, View} from 'react-native';
import {NavigationContainer} from '#react-navigation/native';
import Home from './src/screens/Home';
import Details from './src/screens/Details';
import {createStackNavigator} from '#react-navigation/stack';
import {DarkTheme, Text, Title} from 'react-native-paper';
const Stack = createStackNavigator();
const App = () => {
const Darkthemebtntoggle = () => {
return (
<Details />
);
};
return (
<>
<NavigationContainer>
<StatusBar barStyle="dark-content" />
<Stack.Navigator screenOptions={{headerTitleAlign: ''}}>
<Stack.Screen
name="Home"
component={Home}
options={{
headerTitle: (props) => (
<Darkthemebtntoggle {...props} />
),
}}
/>
</Stack.Navigator>
</NavigationContainer>
</>
);
};
export default App;
Here is also Details.js component code:
import React, {useState} from 'react';
import {View, Text} from 'react-native';
import {TouchableRipple, Switch, Title} from 'react-native-paper';
function Details() {
const [isDartheme, setDarkTheme] = useState(false);
const togglemethod = () => {
setDarkTheme(!isDartheme);
};
return (
<View style={{flexDirection:"row"}}>
<View >
<Title>
<Text >Home</Text>
</Title>
</View>
<View style={{ paddingLeft:10, flexDirection:"row"}}>
<TouchableRipple
onPress={() => {
togglemethod();
}}>
<View pointerEvents="none">
<Switch value={isDartheme} />
</View>
</TouchableRipple>
</View>
</View>
);
}
export default Details;
Here is a screenshot of the behavior of the header:

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
},
})
);

How do I hide material bottom tab navigator in a nested stack navigator in react native

I'm using material Bottom Tab Navigator, My app is structured such that, some tabs contain a stack navigator.
I want to hide the bottom tabs when a user navigates to another stack in the stack navigator.
I'm using react navigation v5.
I don't want the bottom tabs showing when a user has already navigated to a stack.
I found the answer at this link:
Tab bar can now be hidden #20
What you should do is use the barStyle attribute with the 'none' property, which would look like this:
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs'
const BottomTab = createMaterialBottomTabNavigator()
const TabsNavigator = () => (
<BottomTab.Navigator
initialRouteName='Home'
barStyle={{
display: 'none'
}}
>
// Screens
</BottomTab.Navigator>
)
Then you can control that property with a variable, something similar to this:
...
barStyle={{
display: isTabVisible ? null : 'none'
}}
...
However, to control which screens are displayed or not, you can use redux or some way to control the state of the variable isTabVisible as shown in the following link:
material-bottom-tabsのTabを非表示する方法〜React navigation〜
Yeap it's in japanese
I made you a basic example of what you're asking. I hope this what you're looking for :
import React from 'react'
import { Button, View, Text, StyleSheet } from 'react-native'
import { NavigationContainer } from '#react-navigation/native'
import { createMaterialBottomTabNavigator } from '#react-navigation/material-bottom-tabs'
import { createStackNavigator } from '#react-navigation/stack'
const Screen1 = ({ navigation }) => (
<View style={styles.component}>
<Button title="Go to NoBottomComp" onPress={() => navigation.navigate('NoBottomComp')} />
</View>
)
const Screen2 = () => <View style={styles.component}><Text>Screen 2 component</Text></View>
const NoBottomComp = () => <View style={styles.component}><Text>Screen without bottom component</Text></View>
const Footer = createMaterialBottomTabNavigator()
const FooterNav = () => (
<Footer.Navigator>
<Footer.Screen name="Screen1" component={Screen1} />
<Footer.Screen name="Screen2" component={Screen2} />
</Footer.Navigator>
)
const Main = createStackNavigator()
export default props => (
<NavigationContainer>
<Main.Navigator>
<Main.Screen name="BottomNav" component={FooterNav} />
<Main.Screen name="NoBottomComp" component={NoBottomComp} />
{/* As many screens as you want to be without bottom tabs */}
</Main.Navigator>
</NavigationContainer>
)
const styles = StyleSheet.create({
component: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}
})