React-native giving props through Tab navigator - react-native

i am trying to give props through a navigator.
This is what i have
export const NavigationMenu = ({ language, setLanguage }: props) => {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Setting" component={SettingScreen}/>
<Tab.Screen name="Input" component={Input}/>
</Tab.Navigator>
</NavigationContainer>
);
};
how do i add the language and setLanguage props to the tab screens?

i fixed it by doing this:
<Tab.Screen
name="Input"
children={() => <Input language={language} />}
/>

Related

UI Kitten and initialRouteName

I am trying to set a specific tab to start the application. UI kitten's navigation, starts up with the first tab, and actually I want the tab that is in the second position to be the first to appear to the user. I can not find how to set the initialRoute withtin UI kittens Bottom tab bars. I post some of my code so it can be clear:
const { Navigator, Screen } = createBottomTabNavigator();
const BottomTabBar = ({ navigation, state }) => (
<View>
<Divider />
<BottomNavigation
appearance="noIndicator"
selectedIndex={state.index}
onSelect={(index) => navigation.navigate(state.routeNames[index])}
>
<BottomNavigationTab title="screen1" icon={icon1} />
<BottomNavigationTab title="screen2" icon={icon2} />
<BottomNavigationTab title="screen3" icon={icon3} />
</BottomNavigation>
</View>
);
export const BottomTabsNavigator = () => (
<Navigator tabBar={(props) => <BottomTabBar {...props} />}>
<Screen name="screen1" component={Screen1}/>
<Screen name="screen2" component={Screen2}/>
<Screen name="screen3" component={Screen3} />
</Navigator>
);
export const AppNavigator = () => {
return (
<SafeAreaView>
<NavigationContainer>
<Navigator headerMode='none' >
<Screen name={'BottomTabs'} component={BottomTabsNavigator} />
</Navigator>
</NavigationContainer>
</SafeAreaView>
)
};
I've tried in multiple positions but it doesn't seem to work.
Within the following component:
<Navigator tabBar={(props) => <BottomTabBar {...props} />}>
You need to use the following prop: initialRouteName, like so:
<Navigator initialRouteName={'namehere'} tabBar={(props) => <BottomTabBar {...props} />}>
This is telling the navigator what screen to start on when initially rendered! Hope this helps.
For anyone outside of this question that has landed on this page, you can specify what screen you want the navigator to "start" on by using the prop: initialRouteName. This then tells the navigator to use this as your landing page!

How to wrap two different tabs with different context in React Navigation 5

My React Native app has a Tab Navigator with two tabs, simple like that:
<Tab.Navigator>
<Tab.Screen
name="Public"
component={PublicNavigator}
options={{
tabBarIcon: () => <Ionicons name="ios-navigate" size={24} />,
}}
/>
<Tab.Screen
name="Private"
component={PrivateNavigator}
options={{
tabBarIcon: () => <Ionicons name="ios-pin" size={24} />,
}}
/>
</Tab.Navigator>
Since the screens within these two tabs have to access two different APIs and since I am using Apollo Client 3.x, the easy way would be to wrap these two screens so that they can access their respective clients, like that:
<Tab.Navigator>
<ApolloProvider
client={
new ApolloClient({
uri: '/graphql/public',
cache: new InMemoryCache(),
})
}>
<Tab.Screen
name="Public"
component={PublicNavigator}
options={{
tabBarIcon: () => <Ionicons name="ios-navigate" size={24} />,
}}
/>
</ApolloProvider>
<ApolloProvider
client={
new ApolloClient({
uri: '/graphql/public',
cache: new InMemoryCache(),
})
}>
<Tab.Screen
name="Private"
component={PrivateNavigator}
options={{
tabBarIcon: () => <Ionicons name="ios-pin" size={24} />,
}}
/>
</ApolloProvider>
</Tab.Navigator>
However, this is not allowed by React Navigation, the returned error is: A Navigator can only contain Screen components as its direct children.
Now, I can wrap the child navigators themselves whenever I try to render them but the problem I have is that this would re-create the client every time the navigator re-renders, which seems to be pretty often.
Anyone else has another idea on how to resolve this?
You make the screen into a component, then wrap that navigator. Then place that component in the tabNavigator.
I believe this is the solution that would work for you.
const MainStack = createNativeStackNavigator();
function MainStackScreen() {
return (
<ListContextWrapper>
<MainStack.Navigator
initialRouteName="MainScreen"
screenOptions={({ route }) => ({
headerShown: false,
})}
>
<MainStack.Screen name="MainScreen" component={MainScreen} />
<MainStack.Screen name="FilterModal" component={FilterModal} />
<MainStack.Screen name="DescriptionModal" component={DescriptionModal} />
</MainStack.Navigator>
</ListContextWrapper>
);
}
then in your tabNavigator:
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator
...
<Tab.Screen name="Main" component={MainStackScreen}
</Tab.Navigator>
/>

How to add Button to a BottomTabNavigator on React Native?

My goal is to have both Top and Bottom navigation bar for Home, Dashboard, and Album, but not for the SignIn. Here's the catch, I wish to put the button on the bottom instead of on the top.
The last remaining puzzle is how to add a Sign In button to the Bottom Navigation Bar.
The roadblock is if you write <Tab.Screen name="Sign In component={SignIn} /> and you press a button with parameter onPress={() => navigation.navigate('SignIn')}, it will navigate you to the Tab.Screen instead of Stack.Screen.
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Dashboard" component={Dashboard} />
<Tab.Screen name="Album" component={Album} />
</Tab.Navigator>
);
}
const Stack = createStackNavigator();
function MyStack() {
return (
<Stack.Navigator>
<Stack.Screen options={{title: ''}} name="MyTabs" component={MyTabs} />
<Stack.Screen name="SignIn" component={SignIn} />
</Stack.Navigator>
);
}
export default function App() {
return (
<Provider store={store}>
<NavigationContainer>
<MyStack />
</NavigationContainer>
</Provider>
);
}
You can use the tabbarbutton like below. This would pass the props and render a the touchableopacity and you can have your own onPress.
You can navigate, here i have given an alert
<Tab.Screen name="Settings"
options={({navigation})=> ({
tabBarButton:props => <TouchableOpacity {...props} onPress={()=>navigation.navigate('SignIn')}/>
})}/>

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.

When using react navigation, to hide the parent component header button from the child component?

Stack navigation is parent and tab navigation is child
I want to hide the button when I press the "settings" tab.
using `react-navigation ver.5
please help me.
child
const Tab = createBottomTabNavigator();
const Tabs = () => {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Observatory" component={Observatory} />
<Tab.Screen name="Search" component={Search} />
<Tab.Screen name="Setting" component={Setting} />
</Tab.Navigator>
);
}
parent
const Stack = createStackNavigator();
export default App = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Tabs"
component={Tabs}
options={({ navigation, route }) => ({
headerRight: () => (
<Icon
name="edit"
size={30}
color="#000"
onPress={() => navigation.navigate('Template')}
/>
),
})}
/>
<Stack.Screen name="Template" component={Template} />
</Stack.Navigator>
</NavigationContainer>
);
}