I'm trying to create nested menu in react native drawer. I can create the menu as below but I have to find a way to group items and put them into accordion. This is how I currently create the menu:
import React from 'react';
import PropTypes from 'prop-types';
import { SafeAreaView, ScrollView, StyleSheet,View } from 'react-native';
import { DrawerItems,createDrawerNavigator } from 'react-navigation';
import { Container, Content, Text, List, ListItem } from "native-base";
import {Image,ImageBackground} from "react-native";
import logo from '../images/logofullwhite200.png';
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 20
}
});
const DrawerComponent = props => {
const skippedItems = Object.keys(props.drawerItems).filter(name => props.drawerItems[name].skip);
return (
<ScrollView style={styles.container}>
<SafeAreaView style={styles.container} forceInset={{ top: 'always', horizontal: 'never' }}>
<Content>
<ImageBackground
source={{
uri: "https://raw.githubusercontent.com/GeekyAnts/NativeBase-KitchenSink/master/assets/drawer-cover.png"
}}
style={{
height: 120,
alignSelf: "stretch",
justifyContent: "center",
alignItems: "center"
}}>
<Image
square
style={{ height: 50, width: 150 }}
source={logo}
/>
</ImageBackground>
<DrawerItems
{...props}
onItemPress={({ focused, route }) => {
if (!skippedItems.includes(route.routeName)) {
props.onItemPress({ focused, route });
}
}}
/>
</Content>
</SafeAreaView>
</ScrollView>
);
};
DrawerComponent.propTypes = {
onItemPress: PropTypes.func,
drawerItems: PropTypes.object
};
export default DrawerComponent;
this is the data example
"CreateSale": Object {
"navigationOptions": Object {
"drawerLabel": Object {
"$$typeof": Symbol(react.element),
"_owner": null,
"_store": Object {},
"key": null,
"props": Object {
"i18nKey": "sale.create_sale",
},
"ref": null,
"type": [Function I18nextWithTranslation],
},
},
"screen": [Function KeyboardAwareNavigator],
"userInfo": Object {
"showOnLogin": true,
},
},
"Customer": Object {
"navigationOptions": Object {
"drawerLabel": Object {
"$$typeof": Symbol(react.element),
"_owner": null,
"_store": Object {},
"key": null,
"props": Object {
"i18nKey": "list.title",
},
"ref": null,
"type": [Function I18nextWithTranslation],
},
},
"screen": [Function KeyboardAwareNavigator],
"userInfo": Object {
"showOnLogin": true,
},
}
This is how index.tsx looks
export default new ClientModule({
router: <MainScreenNavigator />,
onAppCreate: [
async (modules: ClientModule) =>
(ref.navigator = createDrawerNavigator(
{
...modules.drawerItems
},
{
// eslint-disable-next-line
contentComponent: props => <DrawerComponent {...props} drawerItems={modules.drawerItems} />
}
))
]
});
I have to put the items in to accordion, they have to look nested such as as below:
Outlets
Customers
Customer
no need to make nested drawer. you can use react-native-collapsible and make custom drawerItem like accordion
yarn add react-native-collapsible
import Collapsible from 'react-native-collapsible';
() => (
<Collapsible collapsed={isCollapsed}>
<SomeCollapsedView />
</Collapsible>
);
Related
I am new to ReactNative programming and .tsx files in general. I'm trying to display a basic FlatList and have copied the below code from the ReactNative docs here: (https://reactnative.dev/docs/flatlist). It's only slightly modified to fit into my ReactNative app which I am editing in Visual Studio code.
Does anyone know the correct way to display a FlatList? I've spent 2-3 days tinkering with this but I'm obviously missing some crucial ingredient. Beats me.
import * as React from "react";
import { useState, Component } from "react";
import EditScreenInfo from "../components/EditScreenInfo";
import { StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar } from "react-native";
// import PaymentScreen from "./PaymentScreen";
import { Driver } from "../models/Driver";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#FFF"
},
container: {
height: 750,
width: 750,
backgroundColor: "tomato"
},
map: {
flex: 1,
height:750,
width:750
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
title: {
fontSize: 18
}
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "First Item",
},
{
id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
title: "Second Item",
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Third Item",
},
];
// tslint:disable-next-line:typedef
const Item = ({ item, onPress, backgroundColor, textColor }: {
item: any;
onPress: any;
backgroundColor: any;
textColor: any;
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
export default class TabFourScreen extends Component {
drivers: Driver[] = []; // fetch these from backend... for now you can STUB
selectedId: any = useState(null);
setSelectedId: any = useState(null);
renderItem: any = ({ item }: {item: any}) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === this.selectedId ? "#6e3b6e" : "#f9c2ff";
// tslint:disable-next-line:typedef
const color = item.id === this.selectedId ? "white" : "black";
return (
<Item
item={item}
onPress={() => this.setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
}
render = () => {
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
</SafeAreaView>
</View>
);
}
}
First of all you can't use hooks like useState in a Class Component, you have to use Function Component: https://reactnative.dev/docs/getting-started#function-components-and-class-components.
Secondly, you have set width: 750 to your SafeAreaView's style, so the text doesn't appear on the screen you see but appears before.
Try this code:
import * as React from 'react';
import { useState, Component } from 'react';
import {
StyleSheet, Text, View, Dimensions, TouchableOpacity, Alert, FlatList, SafeAreaView, StatusBar,
} from 'react-native';
// import PaymentScreen from "./PaymentScreen";
// tslint:disable-next-line:typedef
const styles = StyleSheet.create({
page: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#FFF',
},
container: {
height: 750,
width: '100%',
backgroundColor: 'tomato',
},
map: {
flex: 1,
height: 750,
width: 750,
},
item: {
height: 44,
},
title: {
fontSize: 25,
color: 'white',
},
});
// tslint:disable-next-line: typedef
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
// tslint:disable-next-line:typedef
const Item = ({
item, onPress, backgroundColor, textColor,
}) => (
<TouchableOpacity onPress={onPress} style={[styles.item, backgroundColor]}>
<Text style={[styles.title, textColor]}>{item.title}</Text>
</TouchableOpacity>
);
const TabFourScreen = () => {
const [selectedId, setSelectedId] = useState(null);
const renderItem = ({ item }) => {
// tslint:disable-next-line:typedef
const backgroundColor = item.id === selectedId ? '#6e3b6e' : '#f9c2ff';
// tslint:disable-next-line:typedef
const color = item.id === selectedId ? 'white' : 'black';
return (
<Item
item={item}
key={item.id}
onPress={() => setSelectedId(item.id)}
backgroundColor={{ backgroundColor }}
textColor={{ color }}
/>
);
};
return (
<View style={styles.page}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
</SafeAreaView>
</View>
);
};
export default TabFourScreen;
I removed typescript just to test, feel free to add it again.
don't use this.renderItem use only renderItem
I am following a tutorial but as I code along I am stuck,
Why isn't my FlatList not showing?
App.js is simply returning MessagesScreen "screen".
This is my code for a MessagesScreen:
import React from "react";
import { FlatList } from "react-native";
import ListItem from "../components/ListItem";
const messages = [
{
id: 1,
title: "T1",
description: "D1",
image: require("../assets/mosh.jpg"),
},
{
id: 2,
title: "T2",
description: "D2",
image: require("../assets/mosh.jpg"),
},
{
id: 3,
title: "T3",
description: "D3",
image: require("../assets/mosh.jpg"),
},
{
id: 4,
title: "T4",
description: "D4",
image: require("../assets/mosh.jpg"),
},
];
const MessagesScreen = () => {
return (
<FlatList>
data={messages}
keyExtractor={(message) => message.id.toString()}
renderItem=
{({ item }) => {
return (
<ListItem
title={item.title}
subTitle={item.subTitle}
image={item.image}
/>
);
}}
</FlatList>
);
};
export default MessagesScreen;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
This is my component for the ListItem:
import React from "react";
import { View, StyleSheet, Image } from "react-native";
import AppText from "./AppText";
import colors from "../config/colors";
function ListItem({ title, subTitle, image }) {
return (
<View style={styles.container}>
<Image style={styles.image} source={image} />
<View>
<AppText style={styles.title}>{title}</AppText>
<AppText style={styles.subTitle}>{subTitle}</AppText>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
},
image: {
width: 70,
height: 70,
borderRadius: 35,
marginRight: 10,
},
subTitle: {
color: colors.medium,
},
title: {
fontWeight: "500",
},
});
export default ListItem;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
What I've tried is to use the return inside the "renderItem", but with no work, also done it without. The code doesn't give me any errors, so I can't see where the problem is.
You're accessing a property that doesn't exist on your items: subTitle. Did you mean to use description?
Also, I don't believe you can pass in the result of a require call like that. Try passing the raw url and placing the require in the image={} prop instead
Oh it's just a quick fix.
FlatList should be one tag:
const MessagesScreen = () => {
return (
<FlatList // <--- edit here
data={messages}
keyExtractor={(message) => message.id.toString()}
renderItem=
{({ item }) => {
return (
<ListItem
title={item.title}
subTitle={item.subTitle}
image={item.image}
/>
);
}}
/> // <--- and here
);
};
Here's a codesandbox to demonstrate
I am creating a mobile application. In this project, i created a tabview. I copied the code form an internet source and pasted in my application. Tab is shown normally. But when i swap to next tab, it gives me an error
in console screen. Here are the error details:
TypeError: undefined is not an object (evaluating 'this')
And here is my code:
import React, {useEffect, useState} from 'react';
import {View, StatusBar, Image, StyleSheet, Dimensions} from 'react-native';
import {Container, Button, Text, Header, Body} from 'native-base';
import {useNavigation} from '#react-navigation/native';
import {ScrollView} from 'react-native-gesture-handler';
import { TabView, SceneMap } from 'react-native-tab-view';
const LatestRoute = () => (
<View style={[styles.scene, { backgroundColor: '#ff4081' }]} />
);
const FavoritesRoute = () => (
<View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);
const AllRoute = () => (
<View style={[styles.scene, { backgroundColor: '#673ab7' }]} />
);
const App = () => {
const initialState = {
index: 0,
routes: [
{ key: 'latest', title: 'Latest' },
{ key: 'favorites', title: 'Favorites' },
{ key: 'all', title: 'All' },
],
};
const [ state, setState ] = useState(initialState);
function selectTab ( index ) {
this.initialState = {
index: index,
routes: [
{ key: 'latest', title: 'Latest' },
{ key: 'favorites', title: 'Favorites' },
{ key: 'all', title: 'All' },
],
};
return setState(this.initialState);
}
let navigation = useNavigation();
return (
<Container>
<TabView
navigationState={state}
renderScene={SceneMap({ latest: LatestRoute, favorites: FavoritesRoute, all: AllRoute })}
onIndexChange={ (index) => selectTab(index) }
initialLayout={{ width: Dimensions.get('window').width, height : Dimensions.get('window').height }}
/>
</Container>
);
};
const styles = StyleSheet.create({
btns: {
width: '80%',
marginLeft: 'auto',
marginRight: 'auto',
justifyContent: 'center',
marginTop: '10%',
},
registerTitle: {
color: 'red',
textTransform: 'uppercase',
fontSize: 18,
},
scene: {
flex: 1,
},
});
export default App;
if anyone know the error let me know:
I am beginner with react native expo, just creating my first project. I am able to make a flat list and app is working great so far.
However now I need to make something like this,
As being newbie, I am not sure where to start, It seems like a webview is used but I am not sure how to put flatview into webview, or am I completely on wrong track ?
This is what I coded so far,
import React from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
export default App;
Result:
Code:
import React from "react";
import { FlatList, SafeAreaView, StyleSheet, Text, View } from "react-native";
class App extends React.Component {
state = {
data: [
{ id: "00", name: "Mazda RX-7" },
{ id: "01", name: "McLaren F1" },
{ id: "02", name: "Mini Cooper" },
{ id: "03", name: "BMW 645 Ci" }
]
};
render() {
const columns = 3;
return (
<SafeAreaView>
<FlatList
data={createRows(this.state.data, columns)}
keyExtractor={item => item.id}
numColumns={columns}
renderItem={({ item }) => {
if (item.empty) {
return <View style={[styles.item, styles.itemEmpty]} />;
}
return (
<View style={styles.item}>
<Text style={styles.text}>{item.name}</Text>
</View>
);
}}
/>
</SafeAreaView>
);
}
}
function createRows(data, columns) {
const rows = Math.floor(data.length / columns);
let lastRowElements = data.length - rows * columns;
while (lastRowElements !== columns) {
data.push({
id: `empty-${lastRowElements}`,
name: `empty-${lastRowElements}`,
empty: true
});
lastRowElements += 1;
}
return data;
}
const styles = StyleSheet.create({
item: {
alignItems: "center",
backgroundColor: "#dcda48",
flexBasis: 0,
flexGrow: 1,
margin: 4,
padding: 20
},
itemEmpty: {
backgroundColor: "transparent"
},
text: {
color: "#333333"
}
});
export default App;
Hi I hope to find the answer here, this is my code I used a list item and the navigation worked but all the items go to one screen I want to know how to make each one to go to a different screen and I didn't know how to do it I am new in React native programming
import React, { Component } from 'react'; import {Image , StyleSheet,
View, Text, Button } from 'react-native';
import { ListItem, Icon }from 'react-native-elements';
import { StackNavigator } from 'react-navigation';
import call from 'react-native-phone-call';
class First extends Component {
render() { let pic = {
uri: 'https://www.lscoiffure.fr/images/assistance.jpg' };
return (
<View style={styles.container}>
<View>
<Image source={pic} style={{width: 350, height: 200}}
/>
<View style={{position: 'absolute', left: 0, right: 0, bottom: 0, justifyContent: 'center',marginBottom:20, alignItems: 'center'}}>
<Text style={{color :'#ffffff',fontSize:24}}>Assistance</Text> </View> </View>
{
list.map((item, i) => (
<ListItem
key={i}
title={item.title}
titleStyle={{ color: 'black' }}
chevronColor="black"
leftIcon={{ name: item.icon ,color:'black'}}
onPress={() => this.props.navigation.navigate('HomeScreen')}
/>
))
}
</View>
);
}
}
const list = [
{
title: 'Appeler le service clientèle',
icon: 'perm-phone-msg',
},
{
title: 'FAQ',
icon: 'help',
}, {
title: 'Conditions et mentions légal',
icon :'error',
},
]
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor:'#ffffff'
},
})
export default FirstActivity;
I want to know how to use onPress with condition or any solution you suggest.
Change your list, so that every item in your list contains the page you want to navigate like i do below:
const list = [{
title: 'Appeler le service clientèle',
icon: 'perm-phone-msg',
page: 'HomeScreen'
},
{
title: 'FAQ',
icon: 'help',
page: 'OtherScreen'
}, {
title: 'Conditions et mentions légal',
icon: 'error',
page: 'OtherOtherScreen'
},
]
And then in your navigate method use this page:
onPress={() => this.props.navigation.navigate(item.page)}