Flatlist rendered 4 rows but the data variable only have 3 objects
Array items:
const data = [
{ type: 250, amount: 2, points: 150 },
{ type: 250, amount: 2, points: 150 },
{ type: 250, amount: 2, points: 150 },
];
My flatlist:
<FlatList
style={styles.list}
data={data}
keyExtractor={(item, index) => index.toString()}
contentContainerStyle={{
paddingTop: pxToPercentage(8),
}}
renderItem={({ item }) => {
return (
<View style={styles.rowStyle}>
<Text style={styles.typeStyle}>{item?.type}</Text>
<Text>{item?.amount}</Text>
<Text style={styles.pointStyle}>{item?.points}</Text>
</View>
);
}}
/>
Edit:
There is no error here, but a blank view between flatlist and footer how can i remove it
There is no Error, I ran also the same code in my project, and this is working fine.
import React from "react";
import { FlatList, StyleSheet, Text, View } from "react-native";
export default function App() {
const data = [
{ type: 250, amount: 2, points: 150 },
{ type: 250, amount: 2, points: 150 },
{ type: 250, amount: 2, points: 150 },
];
return (
<View>
<FlatList
data={data}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) => {
return (
<View style={{ backgroundColor: "grey", margin: "10px" }}>
<Text>
{item?.type} | {item?.amount} | {item?.points}
</Text>
</View>
);
}}
/>
</View>
);
}
You can see in the picture, this is the output of the above code, there are only three lists, as I change the background color to grey.
Related
In my app, i have a flat list in my app and there is a button I want to add not in the whole flatlist but some of the list components so that's why i need to call the key id of that specific component to the function.
Here is the code of flat list.
**
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
// keyExtractor= {(item,index) => index}
keyExtractor={item => item.GameId.toString()}
ItemSeparatorComponent={this.renderSeprator}
refreshing = {this.state.refreshing}
onRefresh = {this.handleRefresh}
handlePress={item => item.GameId.toString()}
/>
**
This is the function where i want to call gameID
**
handlePress = () => {
if( this.GameId == 1){
this.setState({
btnvalue1: 'flex'});
console.log('ssss11');
} else {
this.setState({
btnvalue1: 'none'});
}
}
**
You can do like below
Code
import React, {useState} from 'react';
import {FlatList, View, Text} from 'react-native';
const myData = [
{
id: 1,
name: 'React',
},
{
id: 2,
name: 'Native',
},
];
export default function App() {
const [data, setData] = useState(myData);
const renderItem = ({item, index}) => {
return (
<View
style={{
height: 50,
width: '90%',
marginLeft: '5%',
flexDirection: 'row',
borderWidth: 1,
borderColor: 'black',
marginBottom: 10,
}}>
<Text>{item.name}</Text>
{item.name === 'Native' ? (
<View style={{height: 35, width: 35, backgroundColor: 'red'}}></View>
) : null}
</View>
);
};
return (
<View>
<FlatList
style={{marginTop: 50}}
data={data}
keyExtractor={(item, index) => String(index)}
renderItem={renderItem}
/>
</View>
);
}
Hope this helps !!!
Snack expo link
I need to create a screen Catalog(Categories and Products).
I'm using SectionList from React Native in order to achive this.
I need to make that Categories component stick on the top when you scroll product lists.
Is there any library that could help me with this Catalog screen ?
Please look at the image here..
import React from "react";
import { View, StyleSheet, SectionList } from "react-native";
import Text from "../Text";
const DATA = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"],
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"],
},
{
title: "Drinks",
data: ["Water", "Coke", "Beer"],
},
{
title: "Desserts",
data: ["Cheese Cake", "Ice Cream"],
},
];
const TabCategories = () => (
<View>
<Text>Horizontal list of categories</Text>
</View>
);
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const TestSectionList = (props) => {
return (
<View style={styles.container}>
<Text style={styles.SRC}>Some React Component</Text>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
StickyHeaderComponent={TabCategories}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {},
SRC: {
fontWeight: "bold",
borderWidth: 1,
borderColor: "#fff",
padding: 10,
},
item: {
padding: 30,
},
header: {
fontWeight: "bold",
fontSize: 20,
},
});
export default TestSectionList;
stickySectionHeadersEnabled
Makes section headers stick to the top of the screen until the next one pushes it up
ListHeaderComponent
Rendered at the very beginning of the list
renderSectionHeader
Rendered at the top of each SECTION
I think this should do:
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
ListHeaderComponent={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
renderSectionHeader={TabCategories}
stickySectionHeadersEnabled
/>
You can try this library react-native-tabs-section-list
https://github.com/bogoslavskiy/react-native-tabs-section-list
If you are talking about react-native-section-list, it inherits ScrollView props, you can check in the docs, in props section, so it has stickyHeaderComponent prop which should be exactly what you want.
I'm a newbie on react-native.
I want to build personalized data from array to populate sectionLists.
My actual code, extracted from react-native docs is
import React from "react";
import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";
const DATA = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"],
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"]
},
{
title: "Drinks",
data: ["Water", "Coke", "Beer"]
},
{
title: "Desserts",
data: ["Cheese Cake", "Ice Cream"]
}
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) => <Item title={item} />}
renderSectionHeader={({ section: { title } }) => (
<Text style={styles.header}>{title}</Text>
)}
/>
</SafeAreaView>
);
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
marginHorizontal: 16
},
item: {
backgroundColor: "#f9c2ff",
padding: 20,
marginVertical: 8
},
header: {
fontSize: 32,
backgroundColor: "#fff"
},
title: {
fontSize: 24
}
});
export default App;
Here, we have only 2 dimensions to data array. I want to personalize that DATA array sending an image source, and a link to a screen on itemclick, for example.
I mean, I have actually title, data on DATA array. I want to add image and link columns to this DATA array and I want to have a solution to parse it in order to associate the link to props and display an image by its source content on image field.
Could you please tell me how to present that for the array and render it ?
Thanks.
EDIT :
I want to add 2 columns image and link on the DATA array like that :
const DATA = [
{
title: "Main dishes",
data: ["Pizza", "Burger", "Risotto"],
image: [require('../assets/Aquarium.png'), require('../assets/Aquarium.png'), require('../assets/Aquarium.png')]
link: ["Pizza", "Burger", "Risotto"]
},
{
title: "Sides",
data: ["French Fries", "Onion Rings", "Fried Shrimps"]
image: [require('../assets/Aquarium.png'), require('../assets/Aquarium.png'), require('../assets/Aquarium.png')]
link: ["FrenchFries", "OnionRings", "FriedShrimps"]
},
{
title: "Drinks",
data: ["Water", "Coke", "Beer"]
image: [require('../assets/Aquarium.png'), require('../assets/Aquarium.png'), require('../assets/Aquarium.png')],
link: ["Water", "Coke", "Beer"]
},
{
title: "Desserts",
data: ["Cheese Cake", "Ice Cream"]
image: [require('../assets/Aquarium.png'), require('../assets/Aquarium.png')]
link: ["CheeseCake", "IceCream"]
}
];
And I want to change my code like this to present image and link to a stackscreen name but it gives me errors.
return (
<SafeAreaView style={styles.container}>
<SectionList
sections={DATA}
keyExtractor={(item, index) => item + index}
renderItem={({ item }) =>
<TouchableWithoutFeedback
activeOpacity={0.4}
onPress={ () => navigation.navigate(item.link)}>
<View style={{flexDirection: 'row', textAlign: 'left', fontSize: 15, backgroundColor:'transparent', marginTop: 15, marginBottom: 15}}>
<Image source={item.image}/>
<Item title={item.title} />
</View>
</TouchableWithoutFeedback>
}
renderSectionHeader={({ section: { title } }) => (
<View>
<Text style={styles.header}>{title}</Text>
</View>
)}
/>
</SafeAreaView>
);
Could you please help me ?
I use flatList to make a list of elements. I would like to show 15 elements and then add a button "see more" to show the next 15 etc.
I was about tu use this tutorial : https://aboutreact.com/react-native-flatlist-pagination-to-load-more-data-dynamically-infinite-list/
But I don't need to use fetch, I already have set up the data (state.listData) and in fact, I'm a little lost on how to adapt it...
I thought that maybe anyone could help me a little.
Thanks a lot
this.state = {
selectedId: '',
setSelectedId:'',
listData:''
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";
return (
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<Item
item={item}
onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
style={{ backgroundColor }}
/>
<Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
</View>
);
};
initListData = async () => {
let list = await getFlights(0);
if (list) {
this.setState({
listData: list
});
}
};
render() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.listData}
renderItem={this.renderItem}
maxToRenderPerBatch={15}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
);
};
}
I just tried this thanks to #Pramod 's answer :
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.flightsListitem, style]}>
<Text style={styles.h4}>{item.id}</Text>
</TouchableOpacity>
);
export default class FlightsList extends Component {
constructor(props) {
super(props);
this.state = {
selectedId: '',
setSelectedId:'',
listData:'',
page:1,
perPage:2,
loadMoreVisible:true,
displayArray:[]
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === this.selectedId ? "transparent" : "fff";
return (
<View style={{flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center'}}>
<Item
item={item}
onPress={() => this.props.navigation.navigate('UpdateTripsForm')}
style={{ backgroundColor }}
/>
<Image source={require("../../assets/images/arrow.png")} style={{width: 15, height:15, justifyContent: 'center'}}/>
</View>
);
};
initListData = async () => {
let list = await getFlights(0);
if (list) {
this.setState({
listData: list
});
}
};
componentDidMount(){
this.setNewData()
// console.log(tempArray)
}
setNewData(){
var tempArray=[]
if(this.state.listData.length == this.state.displayArray.length){
this.setState({
loadMoreVisible:false
})
}else{
for(var i=0; i<(this.state.page*this.state.perPage); i++){
tempArray.push(this.state.listData)
}
this.setState({
displayArray: tempArray,
loadMoreVisible:true
})
}
}
loadMore(){
this.setState({
page: this.state.page+1
},()=>{
this.setNewData()
})
}
async UNSAFE_componentWillMount() {
this.initListData();
}
render() {
return (
<ImageBackground
source={require("../../assets/images/background.jpg")}
style={styles.backgroundImage}
>
<Header
backgroundImage={require("../../assets/images/bg-header.png")}
backgroundImageStyle={{
resizeMode: "stretch",
}}
centerComponent={{
text: i18n.t("mytrips.title"),
style: styles.headerComponentStyle,
}}
containerStyle={[styles.headerContainerStyle, { marginBottom: 0 }]}
statusBarProps={{ barStyle: "light-content" }}
/>
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.displayArray}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
extraData={this.selectedId}
/>
{this.state.loadMoreVisible == true?
<Button style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}}
title = 'load more'
onPress={()=>{this.loadMore()}}>
</Button>:null}
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
</ImageBackground>
);
};
}
the flatlist is not displayed : I get :
You can user pagination method with per page limit so that you can have granular control
Load the array per page when component mount
On every click increase the per page and based on per page update data of your flat list
And also put a flag which will check when the data has ended which will help to hide the load more button when data ends
Working example: https://snack.expo.io/#msbot01/suspicious-orange
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
SafeAreaView,
SectionList,
Switch,
FlatList
} from 'react-native';
import Constants from 'expo-constants';
import Icon from 'react-native-vector-icons/FontAwesome';
import AwesomeIcon from 'react-native-vector-icons/FontAwesome';
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
export default class App extends Component<Props> {
constructor(props) {
super(props);
this.state = {
page:1,
perPage:2,
loadMoreVisible:true,
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',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'fourth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'fifth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29sd72',
title: 'sixth Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29dr72',
title: 'seventh Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d7w2',
title: 'Eight Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29ad72',
title: 'Nineth Item',
},
{
id: '58694a0f-3da1-471f-bd96-14557d1e29d72',
title: 'Tenth Item',
}],
displayArray:[]
}
}
componentDidMount(){
this.setNewData()
// console.log(tempArray)
}
setNewData(){
var tempArray=[]
if(this.state.DATA.length == this.state.displayArray.length){
this.setState({
loadMoreVisible:false
})
}else{
for(var i=0; i<(this.state.page*this.state.perPage); i++){
tempArray.push(this.state.DATA[i])
}
this.setState({
displayArray: tempArray,
loadMoreVisible:true
})
}
}
loadMore(){
this.setState({
page: this.state.page+1
},()=>{
this.setNewData()
})
}
render() {
return (
<View style={{ flex: 1 }}>
<FlatList
data={this.state.displayArray}
renderItem={({item})=>
<View style={{flexDirection:'row'}}>
<Text style={{fontSize:20}}>{item.title} </Text>
</View>
}
keyExtractor={item => item.id}
/>
{this.state.loadMoreVisible == true?
<View style={{width:'100%', height:10, backgroundColor:'green', justifyContent:'center', alignItems:'center'}} onClick={()=>{this.loadMore()}}>Load more</View>:null
}
</View>
);
}
}
Set data in state (already done ==> this.state.listData)
Set counter in state (initialize with 1)
Set 15 first elements in state (you can name it "renderedData" or something like that) and then increase cuonter to 1
Add a function that increases the "renderedData" by 15 items by increasing the counter by one
Add Footer component to the list which will call the function you created in stage 3
To take only 15( or 30/45/60 etc..) items from the list you can do something like this:
this.setState({ renderedItem: listData.slice(0, counter*15) })
I want to display the FlatList that I created. I want to show the title and artist that is in my data. There is no error but my output would not appear anything.
This is my data:
var track =
[
{ List: 'list1',
data:
[
{id: '1', url: 'http://tegos.kz/new/mp3_full/Luis_Fonsi_feat._Daddy_Yankee_-_Despacito.mp3',title: 'Despacito',artist:'Luis Fonsi'},
{id: '2', url: 'http://tegos.kz/new/mp3_full/5_Seconds_Of_Summer_-_Youngblood.mp3',title: 'YoungBlood',artist:'5SOS'},
]
},
{ List: 'list2',
data:
[
{id: '1111', url: 'http://tegos.kz/new/mp3_full/Yellow_Claw_and_San_Holo_-_Summertime.mp3',title: 'Summertime',artist:'Yelow Claw'},
{id: '2222', url: 'http://tegos.kz/new/mp3_full/Post_Malone_-_Better_Now.mp3',title: 'Better Now',artist:'Post Malone'},
]},
];
module.exports = {track:track};
And this is my FlatList:
export default class SongList extends Component{
render(){
const { navigate } = this.props.navigation;
return(
<View>
<FlatList
data={track}
renderItem={({item,index})=>{
return(
<FlatListItem item={item} index={index}>
</FlatListItem>);
}}
>
</FlatList>
</View>
);
}
}
class FlatListItem extends Component{
render(){
return(
<View style={styles.list}>
<View>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
<Text style={styles.itemArtist}>{this.props.item.artist}</Text>
</View>
</View>
);
}
}
Basically I am able to run the program. But there is nothing showing up on the screen. There is only a blank background.
const styles = StyleSheet.create({
itemArtist:{
textAlign: 'center',
justifyContent: 'center',
fontSize: 23,
borderBottomWidth: 4,
borderBottomColor: '#ccc',
marginTop: 10,
padding: 10,
color: 'blue',
},
itemTitle:{
textAlign: 'center',
justifyContent: 'center',
fontSize: 23,
borderBottomWidth: 4,
borderBottomColor: '#ccc',
marginTop: 10,
padding: 10,
color: 'blue',
},
list:{
flex:1,
}
You should write your code as below:
Your data:
export default [
{
List: 'list1',
data: [
{
id: '1',
url: 'http://tegos.kz/new/mp3_full/Luis_Fonsi_feat._Daddy_Yankee_-_Despacito.mp3',
title: 'Despacito',
artist: 'Luis Fonsi',
},
{
id: '2',
url: 'http://tegos.kz/new/mp3_full/5_Seconds_Of_Summer_-_Youngblood.mp3',
title: 'YoungBlood',
artist: '5SOS',
},
],
},
{
List: 'list2',
data: [
{
id: '1111',
url: 'http://tegos.kz/new/mp3_full/Yellow_Claw_and_San_Holo_-_Summertime.mp3',
title: 'Summertime',
artist: 'Yelow Claw',
},
{
id: '2222',
url: 'http://tegos.kz/new/mp3_full/Post_Malone_-_Better_Now.mp3',
title: 'Better Now',
artist: 'Post Malone',
},
],
},
];
Import your data like this, I assume the data file and your code are in a same folder:
import track from './data';
Your components:
export default class App extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<View>
<FlatList
data={track}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<Text style={styles.itemTitle}>{this.props.item.data[0].title}</Text>
<Text style={styles.itemArtist}>{this.props.item.data[0].artist}</Text>
</View>
<View>
<Text style={styles.itemTitle}>{this.props.item.data[1].title}</Text>
<Text style={styles.itemArtist}>{this.props.item.data[1].artist}</Text>
</View>
</View>
);
}
}
And if you want to show only the data of list1 in your FlatList you should change your code as below:
export default class App extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<View>
<FlatList
data={track[0].data}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
<Text style={styles.itemArtist}>{this.props.item.artist}</Text>
</View>
</View>
);
}
}
You can make your data schema better to show them better too.
Steps to debug :-
try to console track, check if data is coming properly.
add console in componentDidMount and check if item if coming there or not.
Add keyExtractor in flatlist, keyExtractor tells the list to use the ids for the react keys instead of the default key property.
<FlatList
data={track}
keyExtractor={(item, index) => ""+index}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>