How to handle flatlist item data in react-native? - javascript

I'm using React-native Flat List in which i have passed sorted array into data props.Now i want to show items according to date
MY code :
<FlatList
horizontal={true}
keyExtractor={(item, index) => index.toString()}
data={this.state.Data}
renderItem={({ item }) =>
<View>
<Image source = {{uri: item.image}}/>
<Text>{item.date}</Text>
</View>
}
/>
I want my image show according to item.date.For example :
Date - 20-09-2018
Image1 ..Image 2...
Date - 21-09-2018
Image1..Image2 ...
Help me !!

You can use SectionList for this purpose as it provides good API for handling such cases.
<SectionList
style={{ flex: 1 }}
keyExtractor={(item, index) => index.toString()}
renderItem={this.renderItem}
renderSectionHeader={this.renderSectionHeader}
sections={list || []}
ItemSeparatorComponent={this.renderSeparator}
/>
For that you need to map your data and create something like an array of objects as
[
{
heading: 'Date - 20-09-2018',
data: [Image1, Image2]
},
{
heading: 'Date - 21-09-2018',
data: [Image1, Image2]
}
]
So the renderSectionHeader function will be something like:
renderSectionHeader = ({section}) => {
return (
<View>
<Text>{section.heading}</Text>
</View>
)
}
And all the other functions like renderItem, renderSeparator etc. you can define as you want.
Check this link for more info

Related

key should be unique react native error while mapping data array?

I have a listing component in my react native map. in which I'm mapping the list of items in the component. How the problem is. I have been getting warnings that each child should have a unique key. Even though I have given them a unique key but still getting that warning.
here is the code.
<ScrollView horizontal>
{this.state.isLoading === true ? (
[...Array(7)].map((item, index) => <PremiumShimmer key={index} />)
) : this.state.isError === true ? (
<View>
<Text style={{ color: "black" }}>
Facing some issue to load data from server
</Text>
</View>
) : this.state.Data.length === 0 ? (
<Text style={{ color: "black" }}>No Data Founbd</Text>
) : (
this.state.Data.map((item) => (
this.ItemRenderer({item})
))
)}
</ScrollView>
ItemRenderer ({ item }) {
return (
<PremiumItemListComponent item={item} navigation={this.props.navigation} />
);
};
PremiumItemListComponent
<TouchableOpacity
style={styles.listBox}
onPress={() => this.props.navigation.navigate("Detail", { data: this.props.item })}
>
<ImageBackground style={styles.listImage} imageStyle={{ borderRadius: 26}} source={{uri:SERVER_URL.apiUrl+this.props.item.background}}>
<Text style={{color:"white",fontSize:13,paddingLeft:10,fontWeight: 'bold'}}>{this.props.item.name}</Text>
<View style={{ flexDirection: 'row', flexWrap: 'wrap',padding:10}}>
{
[...Array(5)].map((e, i) =>
// 3.688689 will be replaced by rating
// console.log(typeof i,typeof 4, i+1<=4)
<Ionicons name={i+1<=Number((3.688689).toFixed(0))?"star-sharp":"star-outline"} size={15} color="#FFE600" />
)
}
</View>
</ImageBackground>
</TouchableOpacity>
I have console logged item.ids and they are unique 23, 24, and 25.
if You need more code to help. You can ask. Thanks in Advance.
Your code looks right, i don't think the warning you are getting for key is from this specific component, but i would like to add a few things to make your life a little easier.
Never use Index as key. Index will change if your data changes which will eventually make the purpose of keys useless.
Wherever possible use FlatList Component instead of a map since you get a easy keyExtractor Prop and it increases your performance if the list is long
Example : -
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
using the keyExtractor Prop you can pick out and convert a unique value from your data into a key and it automatically adds the key prop into rendered component wrapper.

display image and text from array on react native

I'm new on react native. I want to display images and text from array.
When I'm trying to extract image from my app, It doesn't work, the images are not displayed.
const DATA = [
{
title: "Animaux",
data: ["Poissons","Crevettes","Escargots"],
image: [require('../assets/icon_aquarium_style.png'),require('../assets/icon_aquarium_style.png'),require('../assets/icon_aquarium_style.png')]
}
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const ImageType = ({ image }) => (
<View style={styles.image}>
<Image source={image}/>
</View>
);
export default class InventaireScreen extends React.Component {
render() {
return (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item, image }) =>
<View >
<ImageType source={image}/>
<Item title={item} />
</View>
}
renderSectionHeader={({ section: { title } }) => (
<View>
<Text>{title}</Text>
</View>
)}
/>
</SafeAreaView>
);
}
}
the images are not displaying.
Could you please tell me where I'm wrong ?
Thanks.
EDIT :
I modified my array like that :
const DATA = [
{
title: "Poissons",
image: require('../assets/icon_aquarium_style.png')
},
{
title: "Crevettes",
image: require('../assets/icon_aquarium_style.png')
},
{
title: "Escargots",
image: require('../assets/icon_aquarium_style.png')
},
];
I try to extract data using render:
export default class InventaireScreen extends React.Component {
render() {
return (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) =>
<View style={{flexDirection: 'row', textAlign: 'left', fontSize: 15, backgroundColor:'white'}}>
<ImageType image={item.image}/>
<Item title={item.data} />
</View>
}
renderSectionHeader={({ section: { title } }) => (
<View>
<Text style={styles.header}>{title}</Text>
</View>
)}
/>
</SafeAreaView>
);
}
}
I want to display section title using title parameter, an image using image source, and a text using data parameter of my array.
I have this error
ERROR TypeError: undefined is not an object (evaluating 'items.length')
``
In Your Statement
renderItem={({ item, image }) =>
the second argument should be index,
Instead of 'image' it should be 'index'
renderItem={({ item, index }) =>
In order to fetch parameter 'image' from your array you will need to change your code like below :
<View >
<ImageType image={item.image}/>
<Item title={item.title} />
</View>
you data object should be an array of objects to map through it, like
var Data = [{title:"Poissons",image:require('../assets/icon_aquarium_style.png')},{title:"Crevettes",image:require('../assets/icon_aquarium_style.png')},{...},{...}]
and then in render item
{({ item }) =>
<View >
<ImageType image={item.image}/>
<Item title={item.title} />
</View>
}
Try correcting renderItem.
renderItem={({ item }) =>
<View >
<ImageType image={item.image}/>
<Item title={item.title} />
</View>
}
and keyExtractor.
keyExtractor={(item, index) => item.title + index}
this keyExtractor will only take the title and index instead of the full object.
and data format.
const DATA = [
{
title: "Poissons",
image: require('../assets/icon_aquarium_style.png')
},
{
title: "Crevettes",
image: require('../assets/icon_aquarium_style.png')
},
{
title: "Escargots",
image: require('../assets/icon_aquarium_style.png')
},
];

How to add custom component inside an Flatlist in React Native?

I have a Flatlist on react native by which its working perfectly, recently saw an UI which has a custom designed compoenent in between the list, kindly check the below reference image
Check this image, a new design named "Safety+" has been added inside an list, How to do this ?
Need to add custom design like below randomly inside and already rendered flatlist ! How to achieve this , as i couldn't find or understand where to start
Please check the image and help in achieving this:
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({item}) => {
return(
<TouchableOpacity style={styles.busCardContainer}
onPress={() => {
console.log(item);
//this.props.navigation.navigate('SeatLayout')
}}
<Text>{item.name}</Text>
>)}}
/>
This is my flatlist code
You can return a fragment with your component and a randomly included component. The condition for inclusion is up to you, i.e. complete chance, every 5th element, etc.
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({item}) => {
return(
<Fragment>
<TouchableOpacity style={styles.busCardContainer}
onPress={() => {
console.log(item);
//this.props.navigation.navigate('SeatLayout')
}}
>
<Text>{item.name}</Text>
</TouchableOpacity>
{Math.random() < 0.5 && ( // example 50% chance to include random component
<RandomComponent>...</RandomComponent>
)}
</Fragment>
)}}
/>
You can render conditionally in your renderItem function: https://reactjs.org/docs/conditional-rendering.html
Additionally, if you want to render your custom component at specific indexes, you can also put index parameter into renderItem. Here is my example:
<FlatList
contentContainerStyle={{ paddingBottom: 50 }}
data={this.state.availableBusList}
keyExtractor={item => item.id}
renderItem={({ item, index }) => {
return index % 5 === 0 ? <CustomComponent /> : <NormalComponent />;
}}
/>

How to add load more features if my API did not have pagination - react native?

In Home screen, I get data "Songs" from API and save it in the state "Big array".
And I use FlatList to render it, so it rendered fine but I have a too long scroll!
so in data FlatList prop, I slice the array like this
<FlatList
data={songs.slice(0,9)}
...
/>
and it renders 10 songs as expected :D But I want to add Load more when scroll to end
My thought is
add a flag in state like
state={
page: 10
}
<FlatList
data={songs.slice(0,this.state.page)}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0}
...
/>
handleLoadMore = () => {
this.state.songs.length <= this.state.page ? this.setState({page: this.state.page + 10, loading: true}) : null
};
So have any other thoughts How can I handle this case?
Edit
Full FlatList code snippet
// recent Songs FlatList
_renderItem = ({item, index}) => {
const {recent_songs} = this.state;
return (
<TouchableNativeFeed
key={item.id}
onPress={() => {
this.props.saveSongs(recent_songs, index);
this.props.isPlaying(true);
this.props.isPauseTrigger(!this.props.isPauseTrigger);
}}
background={TouchableNativeFeedback.Ripple('white')}
delayPressIn={0}
useForeground>
<Card style={styles.card} noShadow={true}>
<FastImage
source={{uri: item.img}}
resizeMode={FastImage.resizeMode.cover}
style={styles.cardImg}
/>
<Body style={styles.cardItem}>
<View style={styles.radioCardName}>
<View style={styles.cardViewFlex}>
<Text
lineBreakMode="tail"
ellipsizeMode="tail"
numberOfLines={1}
style={styles.text}>
{item.name}
</Text>
</View>
</View>
</Body>
</Card>
</TouchableNativeFeed>
);
};
{/* Recent Songs Here*/}
<View style={{marginVertical: 10}}>
<FlatList
style={{flex: 1}}
horizontal={true}
showsHorizontalScrollIndicator={false}
data={recent_songs.slice(0, 10)}
contentContainerStyle={{flexGrow: 1}}
ListEmptyComponent={<EmptyList />}
keyExtractor={(track, index) => track.id.toString()}
initialNumToRender={10}
renderItem={this._renderItem}
/>
</View>
something like this with flatlist and local pagination
constructor(props) {
super(props);
this.state = {
...
itemPerPage : 10
currentPage : 1, // we keep a track inside the state on each page we are for pagination
songs:[], // contain the songs used by flatlist to render
allSongs : [ ] // contain all the songs returned by api
}
}
async componentDidMount() {
// get the songs from api
let allSongs = await GetSONGS();
this.setState({ allSongs , songs: allSongs.slice(0,this.state.currentPage*this.state.itemPerPage ) });
}
handleLoadMore = async() => {
this.setState({
songs: [ ...this.state.songs , allSongs.slice(this.state.currentPage*this.state.itemPerPage,(this.state.currentPage+1)*this.state.itemPerPage ) ] , // concat the old and new data together
currentPage : this.state.currentPage +1
})
}
render(){
return(
<FlatList
data={this.state.songs}
keyExtractor={(item, index) => index.toString()}
initialNumToRender={10} // how many item to display first
onEndReachedThreshold={5} // so when you are at 5 pixel from the bottom react run onEndReached function
onEndReached={() => {
this.handleLoadMore();
}}
/>
)
}
anyway i use RecyclerListView in a previous project to render list of 10 000 elements

How to display a single dimensional array in FlatList

You would think that this would be the easiest thing in the world to find an example of but everthing I found online has always had a JSON file as the data source so there are keys to reference
stuff like this...eg item.name etc
const list = [
{
name: 'Amy Farha',
subtitle: 'Vice President'
},
{
name: 'Chris Jackson',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/adhamdannaway/128.jpg',
subtitle: 'Vice Chairman'
},
... // more items
]
keyExtractor = (item, index) => index.toString()
renderItem = ({ item }) => (
<ListItem
title={item.name}
subtitle={item.subtitle}
leftAvatar={{
source: item.avatar_url && { uri: item.avatar_url },
title: item.name[0]
}}
/>
)
My data source is just a plain single dimension array, no keys or identifiers of any kind. The data is what it is and wont be changed
data = ['value1','value2','value3',...]
The code I have so far (which obviously doesnt work) is
import React, { Component } from 'react'
import { FlatList, ListItem } from 'react-native'
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem
key={item.id}
/>
)}
/>
Im guessing I need to use the keyExtractor somewhere to generate an id but how do I reference the actual values in the data to display them if it doesnt have an identifier in the data like a json would?
Try this:
<FlatList
data={this.state.data}
keyExtractor={item => item}
renderItem={({ item }) => (
<ListItem
title={item}
/>
)}
/>
const ListItem = ({ title }) => (
<View>
<Text>{title}</Text>
...
</View>
);

Categories