Using StackScreen options from #react-navigation/native - react-native

I need to set a button on screen right side header.
import { useNavigation } from '#react-navigation/native';
const App = () => {
const navigation = useNavigation()
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={{headerShown: false}} />
<Stack.Screen name="Next" component={NextScreen} options={{
headerRight: () => <Button title="Done" onPress={() => navigation.navigate('Home')}/>,
headerLeft:null
}} />
<Stack.Screen name="SelectPatient" component={SelectPatientScreen} />
</Stack.Navigator>
</NavigationContainer>
)
}
error message shows that Couldn't find a navigation object. Is your component inside ascreen in a navigator?
I also use navigation in HomeScreen and it works. Error occurs in App.js.
how can i put navigation object onPress.
Thanks.

Just an addition to Guruparan's answer, you can't do const navigation = useNavigation() outside of a navigator

Related

How to handle authentication on multiple navigators (react-navigation) in React Native?

Here is my tab navigator present in MainNavigator.js,
const MainNavigator = () => {
return (
<Tab.Navigator>
<Tab.Screen
name={'Home'}
component={Home} />
<Tab.Screen
name={'About'}
component={About} />
<Tab.Screen
name={'Profile'}
component={Profile} />
</Tab.Navigator>
)
}
I have an AuthNavigator.js which includes a stack navigator,
const AuthNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen name={'Login'} component={Login} />
<Stack.Screen name={'Signup'} component={Signup} />
</Stack.Navigator>
}
So, I have a logout button on my Profile Screen in Tab Navigator. I want to Navigate to Login Screen in AuthNavigator with the onPress event. Here is how I tried this,
const Profile = ({navigation}) => {
const logoutHandler = () => {
navigation.navigate('Login');
}
<SafeAreaView>
<TouchableOpacity onPress={logoutHandler}>
<Text>Logout</Text>
</TouchableOpacity>
</SafeAreaView>
}
However, this is not working. As a beginner to React Native I have no idea how to link this Login route into a Stack screen. Really appreciate it if somebody could save my day. Thankyou so much.
Manage 1 state globally (using redux or some other state management tool) and that is isAuthenticated.
Then in your App.js or where ever you have defined your root navigator do the changes likewise : -
<NavigationContainer>
{ isAuthenticated ? <AuthRoutes /> : <UnAuthRoute />
</NavigationContainer>
On login and logout you'll have to update this isAuthenticated state and then routes will be taken care as per the state

A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'BottomTap')

I was trying to use TabNavigator in expo, but I have a problem, I have created a component where I have all the routes in a Tab, and in the other component I am only importing it.
in this component I have all the routes of my app:
const AppRouter = () => {
const Stack = createNativeStackNavigator();
const { user } = useContext(AuthContext);
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
}}
>
{!user ? (
<>
<Stack.Screen name="login" component={Login} />
<Stack.Screen name="register" component={Register} />
</>
) : (
<>
<BottomTap />
</>
)}
</Stack.Navigator>
);
};
and in this component I am creating the Tabs with their routes:
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs";
import Home from "../../screens/Home";
const Tab = createBottomTabNavigator();
const BottomTap = () => {
return (
<Tab.Navigator>
<Tab.Screen name="home" component={Home} />
</Tab.Navigator>
);
};
export default BottomTap;
Like the error says, navigators can only contain other navigators - not even custom components that contain only navigators. You can solve this by putting your tab navigator component inside a screen.
Instead of
<BottomTap />
Use
<Stack.Screen name="bottomTap" component={BottomTap} />
You can read more about this in the "Nesting Navigators" section of the React Navigation docs: https://reactnavigation.org/docs/nesting-navigators/
You are adding a React component inside of a navigator instead of 'Screen', 'Group' or 'React.Fragment'. The correct way to add a navigator inside another is:
...
{!user ? (
<>
<Stack.Screen name="login" component={Login} />
<Stack.Screen name="register" component={Register} />
</>
) : (
<>
<Stack.Screen name="bottomTap" component={BottomTap} />
</>
)}
...

reset stack navigation when move from drawer navigation

I have a drawer navigation like that
const DrawerNavigatorRoutes = (props) => {
return (
<Drawer.Navigator>
<Drawer.Screen
name="homeScreenStack"
component={homeScreenStack}
/>
<Drawer.Screen
name="Profile"
component={profileScreenStack}
/>
</Drawer.Navigator>
);
};
When I click homeScreenStack the stack navigation is like that
const homeScreenStack = ({ navigation }) => {
return (
<Stack.Navigator initialRouteName="Dashboard">
<Stack.Screen
name="Dashboard"
component={Dashboard}
/>
<Stack.Screen
name="screen2"
component={screen2}
/>
....
</Stack.Navigator>
);
};
I also have some tab navigation in homeScreenStack So I want that when ever I click on homeScreenStack from drawer navigation Dashboard screen will open But in current scenario it didn't reset the stack. I am using react navigation 5
If I'm reading what you're asking correctly, you should be able to use the unmountOnBlur and set that to true on your drawer navigator to reset your stack. Then when you navigate back to your drawer navigator it will reset your stack navigator. So your code would look like:
const DrawerNavigatorRoutes = (props) => {
return (
<Drawer.Navigator
unmountOnBlur: true,
>
<Drawer.Screen
name="homeScreenStack"
component={homeScreenStack}
/>
<Drawer.Screen
name="Profile"
component={profileScreenStack}
/>
</Drawer.Navigator>
);
};

navigation.navigate on a button in headerRight of the Stack Navigator

Firstly, I have the same issue as Button linking in headerRight. But their solution was simply using functional over component. I cannot simply switch to functional code as I need to use componentDidMount, so I really need solution for a component based headerRight navigation usage.
Stack
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Root"
component={BottomTabs}
options={{
headerRight: ({ navigation }) => (
<View>
<Button
onPress={() => navigation.navigate('Profile')}
</Button>
</View>
),
}}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
);
}
BottomTabs
const BottomTabs = createBottomTabNavigator();
function MyTabs() {
return (
<BottomTabs.Navigator
...
This will bring an error that navigation is not available there. Okay that's right, as you cannot use navigation directly in the definition of the Stack Navigator.
Even using:
headerRight: () => {
return <ProfileButtonScreen/>
},
did not help as on that component I still not have the navigation available.
This is too less info but is already going in the right direction. And finally this gave me the idea about misusing the BottomTabs for the defining of the headerRight.
Stack
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen
name="Root"
component={BottomTabs}
/>
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
);
}
BottomTabs
const BottomTabs = createBottomTabNavigator();
function MyTabs({ navigation, route }) {
navigation.setOptions({
headerRight: () => (
<View>
<Button
onPress={() => navigation.navigate('Profile')}
title="To Profile"
>
</Button>
</View>
),
});
return (
<BottomTabs.Navigator
...
This will now let you have a clickable button on stack navigation header.

React navigation 5 - header is not shown

Trying to update my app to react navigation 5 and been confronting some issues.
First of all, the header does not show up. Snips from the code:
[from App.js]
const Tab = createBottomTabNavigator();
function App() {
return (
<NavigationContainer>
<Tab.Navigator >
<Tab.Screen name="Home" component={HomeScreen} options={{ title:'some title' }}/>
<Tab.Screen name="Upload" component={UploadScreen} />
<Tab.Screen name="Find" component={FindScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
export default App;
and the style of the current screen:
<View style={{flex:1, flexDirection:'column',justifyContent:'space-between'}}>
Here is a screenshot of the app on an Android emulator (and it looks the same on my phone):
As you can see, the header is not shown, the tab navgiation does not right, and so are the buttons (something changed about their background). I did not change anything in the app besides upgrading to react-navigation 5..
Thanks for the help!
Tab navigators do not have header support. You have to wrap your tab navigator inside a stack navigator.
import { createStackNavigator } from "#react-navigation/stack";
// ... other imports
export const App = () => {
return (
<NavigationContainer>
<StackNavigator />
</NavigationContainer>
);
}
const Stack = createStackNavigator();
const StackNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Tabs" component={TabNavigator} />
</Stack.Navigator>
);
}
const Tab = createTabNavigator();
const TabNavigator = () => {
return (
<Tab.Navigator >
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Upload" component={UploadScreen} />
<Tab.Screen name="Find" component={FindScreen} />
</Tab.Navigator>
);
}