navigation.navigate() doesn't work on my nested navigations - react-native

Here I'am testing with react navigation v6.
When I press "Go To Log-In" button,
it prints "navigation.navigate is not a function.
Here is my Main Navigation
const DrawerNavigator = () => {
return (
<Drawer.Navigator>
<Drawer.Screen name="User" component={MainStackNavigator} />
<Drawer.Screen name="Notification" component={BottomTabNavigator}
options={ { headerTitle: props => <LogoTitle {...props} /> }}
/>
</Drawer.Navigator>
);
};
here is my one of my nested Navigation
const MainStackNavigator = () => {
return (
<Stack.Navigator screenOptions={screenOptionStyle}>
<Stack.Screen name="Item" component={Items} />
<Stack.Screen name="Profile" component={Profile} />
<Stack.Screen name="LogIn" component={LogIn} />
<Stack.Screen name="Detail" component={Detail} />
</Stack.Navigator>
);
};
const ContactStackNavigator = () => {
return (
<Stack.Navigator screenOptions={screenOptionStyle}>
<Stack.Screen name="Profile" component={Profile} />
</Stack.Navigator>
);
};
Here is my Log in Button in a component named "Items"
export default function Items(navigation) {
useEffect(() => {
console.log("ITem navi: ", navigation);
}, [])
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text>Items !</Text>
<Button title="Go to Log-In" onPress={() => navigation.navigate('LogIn')} />
<AccountList />
</View>
);
}
I'am stuck in this error for hours.
Please help me to solve it.

You are accessing it the wrong way
this line
export default function Items(navigation) {
Should be
export default function Items({navigation}) {
Basically you will get all the props as a single parameter which you can destruct and access the navigation prop

In your code complier don't know what is navigation so you need wrap that in porps params like below
export default function Items({navigation}) {

Related

navigation.goBack not working in react native

This is the structure of my project: Tab navigator has two screens DailyTab and WeeklyTab. DailyTab is itself a stack navigator which has two screens Daily and Todos. Daily is the default screen and I am able to navigate from Daily to Todos but the same Todos screen appears when I press the back button on Todos(I expect it to take me to Daily screen)
Main:
const Main = () => {
const Tab = createBottomTabNavigator();
return (
<NavigationContainer independent={true}>
<Tab.Navigator>
<Tab.Screen
name="DailyTab"
component={DailyTab}
/>
<Tab.Screen
name="WeeklyTab"
component={WeeklyTab}
/>
</Tab.Navigator>
</NavigationContainer>
);
};
DailyTab:
const DailyTab = () => {
return (
<NavigationContainer independent={true}>
<Stack.Navigator initialRouteName="Daily">
<Stack.Screen
name="Daily"
component={Daily}
options={{headerShown: false}}
/>
<Stack.Screen
name="Todos"
component={Todos}
options={{headerShown: false}}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
const Daily = ({navigation}) => {
return (
<View style={globalStyles.overallBackground}>
<Navbar />
<Calendar navigation={navigation} />
</View>
);
};
Todos:
const Todos = ({route, navigation}) => {
return (
<View style={globalStyles.overallBackground}>
<Navbar />
<Button title="back" onPress={()=>navigation.goBack()} ></Button>
</View>
);
};
Where am I going wrong?
Try out putting --
this.props.navigation.goBack()

React has detected a change in the order of Hooks called by StackNavigator

I'm using StackNavigator, inside TabNavigator, inside Drawer Navigator.
Trying to redirect to nested Stacks but returns error.
Warning: React has detected a change in the order of Hooks called by StackNavigator. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks:
TypeError: undefined is not an object (evaluating 'prevDeps.length')
What's wront with that?
Why it doesnt redirect to stack.screen below main screen?
my redirect:
<TouchableOpacity style={styles.accessButton} onPress={() => navigation.navigate('Home', {
screen: 'Events'
})}>
My main.js (navigator)
return (
<NavigationContainer theme={NavigationTheme} ref={navigationRef}>
<StatusBar barStyle={darkMode ? 'light-content' : 'dark-content'} />
<Drawer.Navigator
drawerStyle={{ width: '100%' }}
drawerContent={(props) => <DrawerContent {...props} />}
>
<Drawer.Screen name="Startup" component={IndexStartupContainer} />
{isApplicationLoaded && BeforeLogin != null && (
<Drawer.Screen name="Main" component={BeforeLogin} />
)}
</Drawer.Navigator>
</NavigationContainer>
)
my tabbar navigator:
return (
<Tab.Navigator tabBarOptions={{showLabel: false}} lazy>
<Tab.Screen name="Home" component={HomeNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="home" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="SearchNavigator" component={SearchNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="search1" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="FAQNavigator" component={FAQNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<AntDesign name="questioncircleo" size={39} color={colors.text} />
);
},
}}
/>
<Tab.Screen name="ContactNavigator" component={ContactNavigator}
options={{
tabBarIcon: ({size,focused,color}) => {
return (
<Feather name="phone" size={39} color={colors.text} />
);
},
}}
/>
</Tab.Navigator>
)
and my HomeNavigator:
const HomeNavigator = ({ navigation }) => {
const Stack = createStackNavigator()
const { t } = useTranslation()
return (
<Stack.Navigator>
<Stack.Screen
options={headerStyle_1}
name='Index'
title={t('title.homepage')}
component={HomepageController}
/>
<Stack.Screen
options={headerStyle_1}
name='Events'
title={t('title.events')}
component={EventsController}
/>
</Stack.Navigator>
)
}

Combine Stack, Drawer and Tab navigator in react-native

I've currently built, this navigation system but I feel like i've got it a bit wrong as in the order of things. I'm slowly developing issues such as not being able to hide the drawer navigator on certain screens of the tav navigator and etc..
Would someone be able to help me organise the navigation so that it makes a bit more sense?
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const Tab = createMaterialTopTabNavigator();
const SwipeTabNavigator = () => {
return (
<Tab.Navigator
sceneContainerStyle={{
backgroundColor: theme['primaryColor'],
}}
tabBarOptions={{
style: {
display: 'none',
backgroundColor: '#08457e',
},
}}>
<Tab.Screen name="Component1" component={Component1} />
<Tab.Screen name="Component2" component={Component2} />
<Tab.Screen name="Component3" component={Component3} />
</Tab.Navigator>
);
};
const MainStackNavigator = () => {
return (
<Stack.Navigator
screenOptions={{
cardStyle: {backgroundColor: theme['primaryColor']},
header: () => <MenuComponent />,
}}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="SwipeTabNavigator" component={SwipeTabNavigator} />
<Stack.Screen name="List" component={ListScreen} />
<Stack.Screen name="Detail" component={DetailScreen} />
</Stack.Navigator>
);
};
const App = () => {
return (
<Root>
<NavigationContainer>
<Drawer.Navigator
screenOptions={{swipeEnabled: false}}
drawerContent={(props) => <SidebarComponent {...props} />}
initialRouteName="Login">
<Drawer.Screen name="List" component={MainStackNavigator} />
</Drawer.Navigator>
</NavigationContainer>
</Root>
);
};
export default App;
After user logs in the navigation navigates to "SwipeTabNavigator", and I would like the drawer to be available at each screen :/
Any refactor help would be a blessing, thank you!

How can I add navigation in the navigation header?

I'm trying to create a button for navigating to "CreateScreen", the button is placed in the header so I wrote it inside <NavigationContainer> as the documentation suggested, but it seems I don't have access to navigation, I don't actually need it inside NavigationContainer, so if you have other suggestions for implementing(for example, implementing the button inside the component) it will be great.
That's What I'm trying to accomplish(part of app.js)
headerRight: () => {
return <TouchableOpacity>
<Feather name="plus" size={30} onPress={() => navigation.navigate('Create')} />
</TouchableOpacity>
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Index">
<Stack.Screen
name="Index"
component={IndexScreen}
options={{
title: 'Home',
headerRight: () => {
return (
<TouchableOpacity>
<Feather
name="plus"
size={30}
onPress={
() => navigation.navigate('Create')
//Thats what Im trying to accomplish
}
/>
</TouchableOpacity>
);
},
}}
/>
<Stack.Screen name="Show" component={ShowScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
you can use the useNavigation hook to gain access to the navigation prop:
import { useNavigation } from '#react-navigation/native';
const navigation = useNavigation();
navigation.goBack();
source:
https://reactnavigation.org/docs/use-navigation/
In option will return navigation
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Index">
<Stack.Screen
name="Index"
component={IndexScreen}
//navigation<<<<<<<<<<<<<<<<<<<<<<<<<here
options={({navigation, route}) => ({
title: 'Home',
headerRight: () => {
return (
<TouchableOpacity>
<Feather
name="plus"
size={30}
onPress={() => navigation.navigate('Create')}
/>
</TouchableOpacity>
);
},
})}
/>
<Stack.Screen name="Show" component={ShowScreen} />
<Stack.Screen name="Create" component={CreateScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}

How to call toggleDrawer in React Navigation 5

I got a React-Navigation 5 drawer menu working using gesture, but I also want to add an icon on the right side of the header to toggle the drawer menu.
I have the navigation setup in my App.js like this:
import {NavigationContainer, DrawerActions} from '#react-navigation/native';
//....... other imports
const HomeStack = createStackNavigator();
const HomeStackScreens = () => (
<HomeStack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
onPress={() => DrawerActions.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
}}>
<HomeStack.Screen
name="Home"
component={HomeScreen}
options={{
header:({scene, previous, navigation}) => {
return (
<TouchableOpacity onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
}
}}
/>
<HomeStack.Screen name="Login" component={Login} />
<HomeStack.Screen name="Register" component={Register} />
</HomeStack.Navigator>
);
const ProfileStack = createStackNavigator();
const ProfileStackScreens = () => (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={Profile} />
</ProfileStack.Navigator>
);
const SettingStack = createStackNavigator();
const SettingStackScreens = () => (
<SettingStack.Navigator>
<SettingStack.Screen name="Profile" component={Profile} />
</SettingStack.Navigator>
);
const Drawer = createDrawerNavigator();
const DrawerScreens = () => (
<Drawer.Navigator>
<Drawer.Screen name="Home" component={HomeStackScreens} />
<Drawer.Screen name="Profile" component={ProfileStackScreens} />
<Drawer.Screen name="Settings" component={SetttingStackScreens} />
</Drawer.Navigator>
);
class MyApp extends React.Component {
render() {
return (
<NavigationContainer>
<DrawerScreens />
</NavigationContainer>
);
}
}
export default MyApp;
All my others screen are in the form "export default class ScreenName extends React.Component". They are imported in App.js to setup the navigation. The initial screen is Home. The icon is showing correctly on the right side of the header. Calling "DrawerActions.toggleDrawer()" directly does nothing.
I tried "this.props.navigation.toggleDrawer()", and it throws error because "this.props" is undefined.
How can I invoke toggleDrawer() with such a navigation setup? Any help is really appreciated!
Here is the final solution I come up with that requires minimal changes to my original code. The key is to receive "navigation" in screenOptions or options, then I can call navigation methods in the children of screenOptions/options.
<HomeStack.Navigator
screenOptions={({navigation}) => ({
headerStyle: {
backgroundColor: '#5C6BC0',
},
headerTintColor: '#fff',
headerRight: () => {
return (
<TouchableOpacity
style={{paddingRight: 8}}
onPress={() => navigation.toggleDrawer()}>
<Icon name="bars" color="#FFF" size={18} />
</TouchableOpacity>
);
},
})}>