Display custom image and link to a sectionList item on react native - react-native

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 ?

Related

Sticky header on SectionList ReactNative

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.

Add a button "see more" in FlatList?

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) })

React-Native: Is it possible to get the layout positions of the FlatList

As I indicated in the Picture with arrow mark, I would like to get the top positions of FlatList. I tried onLayout props, But it return only null values.
Is there anyway to get the top positions of FlatList?
Check below sample
import React, {Component} from 'react';
import {View, FlatList, StyleSheet, Text} 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',
},
];
export default class HomeScreen extends Component {
findDimesions = layout => {
const {x, y, width, height} = layout;
console.log(x);
console.log(y);
console.log(width);
console.log(height);
};
render() {
return (
<View
onLayout={event => this.findDimesions(event.nativeEvent.layout)}
style={styles.container}>
<FlatList
data={DATA}
renderItem={({item}) => (
<View style={styles.item}>
<Text style={styles.title}>{item.title}</Text>
</View>
)}
keyExtractor={item => item.id}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
Change this according to your requirements.
Hope this helps you. Feel free for doubts.
return (
<View style={styles.container}>
<SafeAreaView style={styles.top} />
<FlatList
...
/>
</View>
);
}
const styles = StyleSheet.create({
top: { flex: 0 },
}

Is it possible to show Custom List Item on a listview in React Native?

I am working on a React Native app, what I was trying is to create a Custom ListView Item just like android where I can use TextViews, ImageView etc as a placeholder. The thing is I didn't find anything yet that could help me.
Desired Output
Listview is deprecated. Do try using Flatlist for the same, Do check out my code in expo snack expo-snack wher it resembles some part, exact design you can make of your own,
below is the code :
import React from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text,Image } from 'react-native';
import Constants from 'expo-constants';
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',
},
];
function Item({ title }) {
return (
<View style={styles.item}>
<Image style={{height:50,width:50}} source={{uri:'https://source.unsplash.com/random'}} />
<Text style={styles.title}>{title}</Text>
<Text style={styles.title2}>{title}</Text>
<Image style={{height:15,width:15,marginLeft:20}} source={{uri:'https://source.unsplash.com/random'}} />
</View>
);
}
export default function App() {
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: Constants.statusBarHeight,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
flexDirection:'row'
},
title: {
fontSize: 10,
},
title2:{
fontSize:12 , marginLeft:10
}
});

React native cannot display flat list

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} />;
}}
/>