I tried to map my data using array.prototype.map() but the data merges into one line, and I tried using flatlist as alternative but it doesn't show anything..... Can someone help me?
const array = [
{name: 'Almer', id: 1},
{name: 'Donat', id: 2},
{name: 'Ardi', id: 3},
];
above is the data
{array.map((e) => {
return (
<View>
<Text>{e.name}</Text>
</View>
);
})}
Any Help or reference will save my day! Thank You
Tried with no error:
Code:
import React from "react";
import { Text, SafeAreaView, View, FlatList } from "react-native";
const array = [
{ name: 'Almer', id: 1 },
{ name: 'Donat', id: 2 },
{ name: 'Ardi', id: 3 },
];
const Test = () => {
return (
<SafeAreaView>
<Text>--- array with map ---</Text>
{array.map((e) => {
return (
<View>
<Text>{e.name}</Text>
</View>
);
})}
<Text>--- FlatList --- </Text>
<FlatList
data={array}
renderItem={({ item }) => (
<View>
<Text>{item.name}</Text>
</View>
)}
keyExtractor={item => item.id.toString()}
/>
</SafeAreaView>
)
};
export default Test;
And snack for furthur changes: Expo example
Related
I'm working with a custom dropdown menu in React Native and am having a problem changing the text when trying to reuse the dropdown in other components.
DropdownMenu.js
export const DropdownMenu = ({dropdownMenuItems}) => {
const [isActive, setIsActive] = React.useState(false);
const onPress = () => {
setIsActive(!isActive);
};
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => setIsActive(false)}
style={{flex: 1}}>
<View>
<TouchableOpacity style={styles.img} onPress={onPress}>
<Image style={styles.imgimg} source={require('./icon.png')} />
</TouchableOpacity>
<Animated.View
style={{
...styles.menu,
opacity: fadeAnim,
transform: [{translateY: translateAnim}],
}}
pointerEvents={isActive ? 'auto' : 'none'}>
<FlatList
data={dropdownMenuItems}
renderItem={({item, index}) => (
<OpenURLButton
url={item.href}
label={item.name}
style={
index === 0
? {borderTopLeftRadius: 8, borderTopRightRadius: 8}
: index === dropdownMenuItems.length - 1
? {borderBottomLeftRadius: 8, borderBottomRightRadius: 8}
: {}
}
/>
)}
/>
</Animated.View>
</View>
</TouchableOpacity>
);
};
In the CompactMenu component, I import my <DropdownMenu /> and set my initial values for my menu:
CompactMenu.js
import React from 'react';
import {SafeAreaView} from 'react-native';
import {DropdownMenu} from './DropdownMenu';
const CompactMenu = () => {
const backgroundStyle = {
backgroundColor: '#fff',
flex: 1,
display: 'flex',
};
const dropdownMenuItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
return (
<SafeAreaView style={backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} />
</SafeAreaView>
);
};
export default CompactMenu;
After importing <CompactMenu /> into another component, I try to change the name & the href in object:
example import:
<CompactMenu dropdownMenuItems={[{name: "changed name", href: "/somePath"}]} />
However, the same strings from CompactMenu.js are displayed in the dropdown.
Being new to RN, I'm not sure of two things here.
1.) Why do the text value for "name" not change when used in a different component?
2.) Shouldn't navigation to another screen use { navigation } instead of href:? I've tried adding onPress={() => navigation.navigate('SomeScreen') in the href but I get an error.
I'm not sure what the correct solution to this is. Any help would be appreciated.
You are not using the props dropdownMenuItems that you are passing to CompactMenu. Instead, you reuse the same menu items for the DropdownMenu component everytime you create a CompactMenu.
You need to use the props that you are passing. I have kept the static items as a default value. If you would like to have these items as well and to add additional items via props, then have a look at the second solution.
Notice that I have integrated some small changes to the rest of the code as well.
const defaultItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
const CompactMenu = ({dropdownMenuItems = defaultItems}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} />
</SafeAreaView>
);
};
const styles = StyleSheet.create({
backgroundStyle: {
backgroundColor: '#fff',
flex: 1,
}
});
Now using the CompactMenu component can receive dropdownMenuItems and will pas them to the DropdownMenu component.
<CompactMenu dropdownMenuItems={[{name: "changed name", href: "/somePath"}]} />
If you want to keep default items and add additional items via props, we could achieve this by merging the provided props with our default items.
const defaultItems = [
{name: 'Messages', href: '/messages'},
{name: 'Trips', href: '/trips'},
{name: 'Saved', href: '/saved'},
];
const CompactMenu = ({dropdownMenuItems}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={[...defaultItems, ...dropdownMenuItems]} />
</SafeAreaView>
);
};
Your second questions addresses the react-navigation framework for react-native. This is a very broad topic and I am assuming from your question that you don't know how this works yet, since you have not setup the necessary structure for using it. I encourage you to go through the documentation first.
In summary, you will need to define a navigator, e.g. a stack-navigator and add a name reference for each of your screens to the dropdown menu. To keep things short, here is a minimal example on how this could work.
const MenuScreen1 = (props) {
return (...)
}
const MenuScreen2 = (props) {
return (...)
}
const CompactMenu = ({dropdownMenuItems, navigation}) => {
return (
<SafeAreaView style={styles.backgroundStyle}>
<DropdownMenu dropdownMenuItems={dropdownMenuItems} navigation={navigation} />
</SafeAreaView>
);
};
const dropdownMenuItems = [
{name: 'Menu Item 1', screen: 'Item1'},
{name: 'Menu Item 2', screen: 'Item2'},
]
const Home = ({navigation}) {
return <CompactMenu navigation={navigation} dropdownMenuItems={dropdownMenuItems} />
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Item1" component={MenuScreen1} />
<Stack.Screen name="Item2" component={MenuScreen2} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
Notice that I have created two screens whose names, which I have defined in the stack navigator, are provided to the CompactMenu. Notice as well that the navigation framework will pas the navigation object only to components that are defined as a screen, thus I have decided to pass the navigation object to the CompactMenu and the DropdownMenu component. You can use the useNavigation hook if you prefer this method.
Now, in your DropdownMenu you can navigate on click to the defined screens.
export const DropdownMenu = ({dropdownMenuItems, navigation}) => {
const [isActive, setIsActive] = React.useState(false);
const onPress = () => {
setIsActive(!isActive);
};
return (
<TouchableOpacity
activeOpacity={1}
onPress={() => setIsActive(false)}
style={{flex: 1}}>
<View>
<TouchableOpacity style={styles.img} onPress={onPress}>
<Image style={styles.imgimg} source={require('./icon.png')} />
</TouchableOpacity>
<Animated.View
style={{
...styles.menu,
opacity: fadeAnim,
transform: [{translateY: translateAnim}],
}}
pointerEvents={isActive ? 'auto' : 'none'}>
<FlatList
data={dropdownMenuItems}
renderItem={({item, index}) => (
<Button
onPress={() => navigation.navigate(item.screen)}
title={item.name}
style={
index === 0
? {borderTopLeftRadius: 8, borderTopRightRadius: 8}
: index === dropdownMenuItems.length - 1
? {borderBottomLeftRadius: 8, borderBottomRightRadius: 8}
: {}
}
/>
)}
/>
</Animated.View>
</View>
</TouchableOpacity>
);
};
I have a list of category from calling external API and I am displaying it in a flatlist like this in horizontal scroll
but it is not changing state onPress , I want it should change color when user click on particular tab/button
my API json format data is like this
const data = [
{
id: '1',
title: 'General'
},
{
id: '2',
title: 'Student-Visa'
},
{
id: '3',
title: 'Study'
},
{
id: '4',
title: 'Festival'
},
{
id: '5',
title: 'NorthIndian-Food'
},
]
and I am using it as
const renderItem = ({ item, index }) => (
<View key={index} style={selectedCategory === item.title ? styles.activeCategory : styles.categoryContainer}>
<TouchableOpacity
activeOpacity={0.6}
underlayColor={COLORS.white}
onPress={()=>handleCategory(item.title)}
>
<Text>{item.title}</Text>
</TouchableOpacity>
</View>
);
return (
<List
data={data}
renderItem={renderItem}
horizontal={true}
style={styles.container}
contentContainerStyle={styles.contentContainer}
showsHorizontalScrollIndicator={false}
keyExtractor={item => item.id.toString()}
/>
)
const handleSelectedCategory = (title) => {
setSelectedCategory(title);
console.log(selectedCategory);
}
const [selectedCategory, setSelectedCategory] = useState();
I am using it as a separate component in another component
<FAQcategory selectedCategory={selectedCategory} />
any suggestion ? or help what I am doing wrong
Thanks in advance
This might help
const [selectedCategory, setSelectedCategory] = useState(0); // should be item index
const handleCategory = (index) => {
setSelectedCategory(index);
};
const renderItem = ({ item, index }) => (
<View
key={index}
style={
selectedCategory === index
? styles.activeCategory
: styles.categoryContainer
}
>
<TouchableOpacity
....
onPress={() => handleCategory(index)} // send index in param
>
....
</TouchableOpacity>
</View>
);
I came across the following React Native code online:
import React, { useState } from 'react';
import { StyleSheet, Text, View, FlatList } from 'react-native';
export default function App() {
const [people, setPeople] = useState([
{ name: 'shaun', id: '1' },
{ name: 'yoshi', id: '2' },
{ name: 'mario', id: '3' },
{ name: 'luigi', id: '4' },
{ name: 'peach', id: '5' },
{ name: 'toad', id: '6' },
{ name: 'bowser', id: '7' },
]);
return (
<View style={styles.container}>
<FlatList
numColumns={2}
keyExtractor={(item) => item.id}
data={people}
renderItem={({item}) => (
<Text style={styles.item}>{item.name}</Text>
)}
/>
</View>
);
}
I do not quite following the snippet related to the renderItem property. why are we using the destructuring syntax {item} . Also this is an object destructuring syntax (using curly braces), but in object destructuring we use keys as variable names. So I am afraid I am completley at a loss to understand the snippet below.
<FlatList
numColumns={2}
keyExtractor={(item) => item.id}
data={people}
renderItem={({item}) => (
<Text style={styles.item}>{item.name}</Text>
)}
Any guidance would be appreciated.
this...
renderItem={({item}) => (
<Text style={styles.item}>{item.name}</Text>
)}
actually mean....
renderItem={(props) => (
<Text style={styles.item}>{props.item.name}</Text>
)}
This technique is called object destruction
check out for more info - https://medium.com/podiihq/destructuring-objects-in-javascript-4de5a3b0e4cb
I am making a music app using react-native-track-player. I made 3 classes called Clusters, Songlist and Play class.
How screen works
Clusters class -> Songlist class -> Play class. Problem for me is from Songlist to Play when I pass props from Songlist class to Play class, I would get error possible unhandled promise rejection and the song is not playing. I created data. First screen shows title and mood(Songlist class). Second screen(Songlist shows the playlist depending on the title that I clicked. Then the Third screen (Play) is where I will get an error after I try to pass props.
This is my where I get my data in another file
const ClusterData = [
{ title: 'Cluster1',
data:
[
{name: 'passionate'},
{name: 'rousing'},
{name: 'confident'},
{name: 'boisterous'},
{name: 'rowdy'}
],
songlist:
[
{
id: '2222',
url: 'http://tegos.kz/new/mp3_full/Post_Malone_-_Better_Now.mp3',
title: 'Better Now',
artist: 'Post Malone',
},
{
id: '2',
url: 'http://tegos.kz/new/mp3_full/5_Seconds_Of_Summer_-_Youngblood.mp3',
title: 'YoungBlood',
artist: '5SOS',
},
]
},
{ title: 'Cluster2',
data:
[
{name: 'rollicking'},
{name: 'cheerful'},
{name: 'fun'},
{name: 'sweet'},
{name: 'amiable'},
{name: 'natured'}
],
songlist:
[
{
id: '1111',
url: 'http://tegos.kz/new/mp3_full/Yellow_Claw_and_San_Holo_-_Summertime.mp3',
title: 'Summertime',
artist: 'Yellow Claw',
},
{
id: '1',
url: 'http://tegos.kz/new/mp3_full/Luis_Fonsi_feat._Daddy_Yankee_-_Despacito.mp3',
title: 'Despacito',
artist: 'Luis Fonsi',
},
]
},
This is my Clusters screen (first screen)
export default class Clusters extends Component{
render(){
return(
<View style={styles.container}>
<SectionList
renderItem={({item,index})=>{
return(
<SectionListItem item={item} index={index}> </SectionListItem>);}}
renderSectionHeader={({ section }) => {
return (<SectionHeader section={section} />);}}
sections={ClusterData}
keyExtractor={(item, index) => item.name}>
</SectionList>
</View>
);
}}
class SectionHeader extends Component {
render() {
return (
<View style={styles.header}>
<Text style={styles.headertext}>
{this.props.section.title}
</Text>
<TouchableOpacity onPress={ () => Actions.SongList({ section: this.props.section}) }>
<Text style ={styles.Play}> Play
</Text>
</TouchableOpacity>
</View>
);
}}
class SectionListItem extends Component{
render(){
return(
<View>
<Text style={styles.moodname}>{this.props.item.name}</Text>
</View>
);
}
}
This is my SongList screen (second screen)
export default class App extends Component {
render() {
return (
<View>
<FlatList
data={this.props.section.songlist}
renderItem={({item,index,rowId})=>{
return(
<FlatListItem item={item} index={index}>
</FlatListItem>);}}>
</FlatList>
</View>
);}}
class FlatListItem extends Component{
render(){
return(
<View>
<TouchableOpacity onPress={ () => Actions.Play({songlist: this.props.item.songlist, item: this.props.item}) }>
<Text style={styles.itemTitle}>{this.props.item.songtitle}</Text>
<Text style={styles.itemArtist}>{this.props.item.artist}</Text>
</TouchableOpacity>
</View>
);}}
So when I click on the songtitle/artist, the app will stop. I think the error could be await TrackPlayer.add(this.props.item.songlist[index]); but I am not sure.
This is my Play screen
import TrackPlayer from 'react-native-track-player';
export default class Play extends Component{
componentDidMount()
{
TrackPlayer.setupPlayer().then(async () => {
// Adds a track to the queue
await TrackPlayer.add(this.props.item.songlist[index]);
// Starts playing it
TrackPlayer.play();
});
}
onPressPlay = () => {
TrackPlayer.play();
};
onPressPause = () => {
TrackPlayer.pause();
};
render() {
return (
<View style={styles.container}>
<View style= {{flexDirection :'column'}}>
<TouchableOpacity style= {styles.play} onPress = {this.onPressPlay}>
<Text style = {{fontWeight:'bold',textAlign:'center',color:'white'}}>Play</Text>
</TouchableOpacity>
<TouchableOpacity style= {styles.pause} onPress = {this.onPressPause}>
<Text style = {{fontWeight:'bold',textAlign:'center',color:'white'}}>Pause</Text>
</TouchableOpacity>
</View>
</View>
);}}
TrackPlayer.setupPlayer().then(async () => {
// Adds a track to the queue
await TrackPlayer.add(this.props.item.songlist[index])
// Starts playing it
TrackPlayer.play();
});
the variable index is undefined, and that's why your app stops
I am trying some react native code which is as follows , I want to set the static images to an image view as follows but it doesn't load
const items = [
{ name: './images/home.png', code: '#1abc9c' }, { name: './images/home.png', code: '#2ecc71' },
{ name: './images/home.png', code: '#3498db' }, { name: './images/home.png', code: '#9b59b6' }
];
return (
<ImageBackground
source={require('./images/marble.jpg')}
style={styles.backgroundImage}>
<GridView
itemDimension={130}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer, { backgroundColor: item.code }]}>
<Image source={require(item.name)}></Image>
</View>
)}
/>
</ImageBackground>
);
Error I get is
calls to require expect exactly 1 string literal argument, but this was found: require(item.name).
Ofcourse I am new to react native so kindly ignore my missed terminology
You try like this
const items = [{ name: require('./images/home.png'), code: '#1abc9c' },{...}]
then
<Image source={item.name}></Image>