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
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.
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')
},
];
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 />;
}}
/>
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
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>
);