How to show Drawer content below Drawer Header - react-native

Using Drawer Navigator from the package of reactnavigation to build a Drawer in our react native project, i want to place drawer below of header like image B,how to do that,
using header: (props) => {return <DrawerHeader {...props} />}, and content as
drawerContent={(props) => {return <DrawerContent {...props} />}}thanks.
<Drawer.Navigator
header: (props) => {return <DrawerHeader {...props} />},
}}
drawerContent={(props) => {
return <DrawerContent {...props} />
}}
>
.....
</Drawer.Navigator >

Rather than passing header component separately you can directly paas it in the drawerContent
<Drawer.Navigator
drawerContent={(props) => {
return(
<>
<DrawerHeader {...props} />
<DrawerContent {...props} />
</>)
}}
>
.....
</Drawer.Navigator >
this way you could style the drawer more efficiently.

Related

React-navigation default drawer icon, how to change it?

How can I change the icon point in the image below? I have not been able to find the documentation in the docs, I would like to change it to a different icon but I have no idea how to do this.
I found documentation about drawerIcon but as far as I know and manage to implement that icon is for the menu items in the drawer it self not for the screen header.
Here is my code:
const Drawer = createDrawerNavigator();
const headerOptions = {
title: 'Task List',
drawerIcon: ({ focused, size, color }) => <Ionicons name="ios-pizza" color="red" size={24} />,
};
const HomeScreen = ({ navigation }, props) => {
return (
<Drawer.Navigator screenOptions={{ drawerType: 'front' }}>
<Drawer.Screen name="TaskList" component={TaskListScreen} options={headerOptions} />
<Drawer.Screen name="TaskView" component={TaskViewScreen} />
<Drawer.Screen name="Notifications" component={Notifications} />
<Drawer.Screen name="Login" component={LoginScreen} />
</Drawer.Navigator>
);
};
But as mention before it renders the icons in the drawer item as shown below
headerLeft: Function which returns a React Element to display on the left side of the header. You can use it to implement your custom left button, for example:
<Drawer.Navigator
screenOptions={({ navigation }) => ({
headerLeft: props => <IconComponent onPress={navigation.toggleDrawer} />,
})}
>
...
</Drawer.Navigator>
<Drawer.Navigator
screenOptions={{
headerTintColor: 'red', // -----> by changing color from here
}} drawerContent={props => <DrawerContent {...props} />} >
<Drawer.Screen />
</Drawer.Navigator >
you can also use a image as a drawer icon.
screenOptions={({ navigation }) => ({
headerLeft: () =>
<Pressable onPress={navigation.toggleDrawer}>
<Text>
<Avatar.Image size={32} source={{ uri: deafaultImage }} />
</Text>
</Pressable >
})}

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!

react-navigation [v6] drawer and stack nesting issues

Like the most common use case, I want to have a drawer in my react-native application where, from all screens header I can open/close the drawer, navigate to them. Also, each screen has an option (button, card,...) that on press should navigate to any other screen.
So I have defined the following structure. But there are several problems;
Drawer cannot recognize which screen in on focus now.
Drawer type check does not give auto-suggestions on navigation prop (e.g. props.navigation.navigate(" /* no suggestion on the present screens in the stack*/"))
On Android I feel that the overall performance drops significantly
So is this a good structure? From the official documentation, I could not find any hint on how to implement it? stack nested in drawer or vise-versa?
export type MainStackParamList = {
HomeScreen: undefined;
OverViewScreen: undefined;
WorkOrdersScreen: {id?: number; description?: string; tabIndex?: number};
PropertiesScreen: undefined;
PropertyDetailScreen: {propertyUnit: PropertyUnit};
};
export type MainDrawerParamList = {MainStack: NavigatorScreenParams<MainStackParamList>};
export type AppNavigationCompositeProps = CompositeScreenProps<
DrawerScreenProps<MainDrawerParamList, 'MainStack'>,
StackScreenProps<MainStackParamList>
>;
//____The navigation part______
const MainStack = createStackNavigator<MainStackParamList>();
const Drawer = createDrawerNavigator<MainDrawerParamList>();
/* the composite type is the only way I found to have access to
drawer fucntions such as toggleDrawer in the stack screens*/
const MainStackScreens = (navigation: AppNavigationCompositeProps) => (
<MainStack.Navigator initialRouteName={'HomeScreen'} screenOptions={MainStackScreenOptions(navigation)}>
<MainStack.Screen name="HomeScreen" component={HomeScreen} />
<MainStack.Screen name="OverViewScreen" component={OverViewScreen} />
<MainStack.Screen name="WorkOrdersScreen" component={WorkOrdersScreen} />
<MainStack.Screen name="PropertiesScreen" component={PropertiesScreen} />
<MainStack.Screen name="PropertyDetailScreen" component={PropertyDetailScreen} />
</MainStack.Navigator>
);
const Navigation: React.FC<{}> = () => {
return (
<NavigationContainer>
<Drawer.Navigator
initialRouteName="MainStack"
screenOptions={{headerShown: false}}
drawerContent={props => <CustomDrawerContent {...props} />}>
<Drawer.Screen name="MainStack" component={MainStackScreens} />
</Drawer.Navigator>
</NavigationContainer>
);
};
export default Navigation;
const MainStackScreenOptions = (navigation: AppNavigationCompositeProps): StackNavigationOptions => {
return {
headerStyle: {backgroundColor: '#00aade'},
headerTintColor: '#fca903',
headerTitleAlign: 'center',
headerTitleStyle: {fontWeight: 'bold', fontStyle: 'italic'},
headerBackTitle: 'GoBack',
headerLeft: () => <IconButton icon="menu" color="white" onPress={() => navigation.navigation.openDrawer()} />
};
};
//___the drawer content is like
const CustomDrawerContent: React.FC<DrawerContentComponentProps> = props => {
return (
<DrawerContentScrollView>
<Drawer.Item label="Home" onPress={() => props.navigation.navigate('HomeScreen')} icon="star" />
<Drawer.Item label="OverView" onPress={() => props.navigation.navigate('OverViewScreen')} icon="star" />
<Drawer.Item label="WorkOrders" onPress={() => props.navigation.navigate('WorkOrdersScreen')} icon="star" />
<Drawer.Item label="Properties" onPress={() => props.navigation.navigate('PropertiesScreen')} icon="star" />
</DrawerContentScrollView>
);
};

Trigger an onPress Function from anonther component

I want to trigger an onPress function from the search icon in the navbar.
This is the search component:
function SearchIcon(props) {
const theme = useSelector(state => state.themer.theme);
return (
<Icon.Button
name="search"
size={22}
color={theme.icons}
backgroundColor={theme.top_tab}
onPress={() => {}}
/>
);
}
export default SearchIcon;
The search component is being called in the specific stack, where it's needed.
<Stack.Screen
name="Home"
component={Home}
options={({navigation, route}) => ({
...,
headerRight: props => (
<View style={{flexDirection: 'row'}}>
<SearchIcon />
<CartIcon navigation={navigation} />
</View>
),
})}
/>
On the home screen, I have an isSeacrhing constant that should change value from false to true and vice versa.
const [data, setData] = React.useState({
isSearching: false,
search: '',
...
});
// TRIGGERED BY SEARCH ICON IN NAV BAR
const toggleSearch = () => setData({...data, isSearching: !isSearching});
{data.isSearching == false ? (
<ScrollView
...
</ScrollView>
) : (
<View>
<TextInput
style={[styles.textInput, [{color: theme.text, ...FONTS.body4}]]}
value={data.search}
placeholder="Search..."
placeholderTextColor={theme.text}
onChangeText={()=>{}}
/>
</View>
)}
Is it possible to trigger the onPress function or is there another way I can make it work? The search icon is on two screen, does calling the same function make the TextInput appear on both?
Wherever you use <SearchIcon /> just add a prop in that like this
<SearchIcon onPress={() => { // Do Something }} />
Then in your SearchIcon
function SearchIcon(props) {
const theme = useSelector(state => state.themer.theme);
return (
<Icon.Button
name="search"
size={22}
color={theme.icons}
backgroundColor={theme.top_tab}
onPress={props.onPress} // Access it here like this
/>
);
}
export default SearchIcon;

TypeError: navigation.getParam is not a function. (In 'navigation.getParam('name')', 'navigation.getParam' is undefined)

I'm nesting screens and passing props to the screens such as header title, and a render of json.
Earlier today everything was working but now it gives me the error of getParams.
HomeStack.js, here in the title I get the title by the FlatList render in the screen which navigates to this one.
<Screen
name='errorHP'
component={errorHP}
options={{
headerTitle: () => <Header navigation={navigation} title={navigation.getParam('name')} />,
headerTitleAlign: 'center',}}
/>
HP.js, here the flatlist renders and will export the render to the page errorHP
<FlatList data={filteredSearch} keyExtractor={(item) => item.key} renderItem={({item}) => (
<TouchableOpacity onPress={() => navigation.navigate('errorHP', item)}>
<Card>
<Text style={globalStyles.titleText}> {item.name} </Text>
</Card>
</TouchableOpacity>
)} />
errorHP.js, here are listed the errors and after click, will pass again params to a new page which gets the error details.
export default function errorHP ({navigation}) {
const data = navigation.getParam('errors');
const errors = Object.keys(data);
return (
<View style={globalStyles.container}>
<FlatList data={errors} renderItem={({item}) => (
<TouchableOpacity>
<Card>
<Text style={globalStyles.titleText}> {item} </Text>
</Card>
</TouchableOpacity>
)} />
I've been messing around and still cant solve this problem.
Thanks for your attention!
You need to get params from the route prop:
export default function errorHP ({navigation, route}) {
const data = route.params.errors;
// whatever
}
And
<Screen
name="errorHP"
component={errorHP}
options={({ route, navigation }) => ({
headerTitle: () => (
<Header navigation={navigation} title={route.params.name} />
),
headerTitleAlign: 'center',
})}
/>