React Native Flatlist rendering items - react-native

I am not able to show my flatlist and I am not sure whether my coding is correct. There is no output if when I run this. It will only show a white screen. My data is correct which is this.props.section.songs. I want to show the title and artist in my text but I am unable to do that.
export default class SongList extends Component
{
renderSongsList() {
return(
<View>
<FlatList
data = {this.props.section.songs}
renderItem={(song, sectionId, rowId) => (
<TouchableOpacity onPress={ () => Actions.Player({songIndex: parseInt( rowId ),songs: this.props.section.songs, section: this.props.section }) }>
<View key={song} style={ styles.song }>
<Text style={styles.itemTitle}>
{ song.title}
</Text >
<Text style={styles.itemArtist}>
{ song.artist }
</Text>
</View>
</TouchableOpacity>
)}
/>
</View>
);
}
render()
{
return (
<View>
{ this.renderSongsList() }
</View>
);}}

export default class SongList extends Component
{
renderSongsList() {
return(
<View>
<FlatList
data = {this.props.section.songs}
// You have to cross check the values you receive here. Better is to receive a array item
//here and pass to the render props
// Or try {song, sectionId, rowId} this in place of (song, sectionId, rowId) see below
renderItem={({song, sectionId, rowId}) => (
<TouchableOpacity onPress={ () => Actions.Player({songIndex: parseInt( rowId ),songs: this.props.section.songs, section: this.props.section }) }>
<View key={song} style={ styles.song }>
<Text style={styles.itemTitle}>
{ song.title}
</Text >
<Text style={styles.itemArtist}>
{ song.artist }
</Text>
</View>
</TouchableOpacity>
)}
/>
</View>
);
}
render()
{
return (
<View>
{ this.renderSongsList() }
</View>
);}}

export default class SongList extends Component
{
renderItems(item){
// Here you can access all items of your json by item.property
// Like your JSON is { id: '1', title: 'Better Now', artist: 'Post Malone', }
// You can access these values as item.id, item.title etc
}
renderSongsList() {
return(
<View>
<FlatList
data = {this.props.section.songs}
renderItem={(item) => this.renderItems(item)}
/>
</View>
);
}
render()
{
return (
<View>
{ this.renderSongsList() }
</View>
);}}

Related

react native navigation refresh component problem

I'm in category page and when i press any of them, it navigates me to the that categories product list. so far so good. when i go back and press another category i get previous categories product list.
there is my some of code
this is how i navigate to product list
render() {
const {navigation} = this.props.navigation;
const categories = category.map((item, index) => {
return (
<TouchableOpacity
key={index}
styles={styles.category}
onPress={() =>
navigation.navigate('ProductList', {
categoryName: item.Menu,
})
}>
<Text> {item.Menu} </Text>
</TouchableOpacity>
);
});
return (
<View style={styles.container}>
{this.state.isData ? (
<View style={styles.container}>
<Text style={styles.title}>Category</Text>
{categories}
</View>
) : (
<ActivityIndicator size="large" color="#0B970B" />
)}
</View>
);
}
}
and this is where i go, i can get navigation props ext. but i cant find where the problem is
import React,{useState,useEffect} from 'react';
import {
View,
ScrollView,
Text,
Image,
StyleSheet,
Dimensions,
ActivityIndicator,
} from 'react-native';
const List = ({navigation}) => {
const [isData, setIsData] = useState(false);
useEffect(() => {
getData();
return null;
}, []);
const getData = async () => {
if (navigation?.route?.params?.categoryName) {
categoryName = navigation.route.params.categoryName;
fetch(global.apiPost + global.token, requestOptions)
.then((response) => response.json())
.then((result) => {
result.forEach((element) => {
if (element.Menu === categoryName) {
products.push(element);
}
});
setIsData(true);
console.log(products, 'products');
console.log(productsByAccessory, 'productsByAccessory');
console.log(productsByTravel, 'productsByTravel');
console.log(productsByBag, 'productsByBag');
})
.catch((error) => console.log('error', error));
}
};
return (
<View style={{flex: 1}}>
<Text style={styles.title}>{categoryName}</Text>
{isData ? (
<View style={{flex: 1}}>
<View style={styles.itemFounds}>
<Text>{data.length + ' item founds'}</Text>
</View>
<View style={{flexDirection: 'row', flexWrap: 'wrap'}}>
<Text>
{productsByAccessory.length} / {productsByTravel.length} /{' '}
{productsByBag.length} / {products.length} asd
</Text>
</View>
</View>
) : (
<ActivityIndicator size="large" color="#0B970B" />
)}
</View>
);
}
export default List
Change your render method
const { navigation } = this.props; // Here was the error
const categories = category.map((item, index) => {
return (
<TouchableOpacity
key={index}
styles={styles.category}
onPress={() =>
navigation.navigate("ProductList", {
categoryName: item.Menu,
})
}
>
<Text> {item.Menu} </Text>
</TouchableOpacity>
);
});
render() {
return (
<View style={styles.container}>
{this.state.isData ? (
<View style={styles.container}>
<Text style={styles.title}>Category</Text>
{categories}
</View>
) : (
<ActivityIndicator size="large" color="#0B970B" />
)}
</View>
);
}
}
render method should have the return statement only. Don't perform any operations inside the render method. Now it should work.

Implement onPress on Flatlist item

I am trying to send the data of the flatlist items when clicked and set to another class.The ontouch is working but I am having the error below in the image. Also how can I send the data of api to the other class and get from another class? I have implemented as follows:
export default class FlatSpeakers extends Component {
constructor(props) {
super(props);
this.state = { isLoading: true, data: [],selectedItem: null, }
const { navigate } = this.props.navigation;
}
onPressItem = () => {
navigate('SpeakersClick')
};
componentDidMount() {
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(res => {
this.setState({
isLoading: false,
data: res.data,
})
})
}
renderItem({ item }) {
return (
<TouchableOpacity onPress={()=>this.onPressItem(item)} >
<Card>
<CardSection>
<View style={styles.thumbnailContainerStyle}>
<Image
style={styles.thumbnailStyle}
source={{ uri: item.image }}
/>
</View>
<View style={styles.headerContentStyle}>
<Text style={styles.headerTextStyle}>{item.title}</Text>
<Text>{item.artist}</Text>
</View>
</CardSection>
</Card>
</TouchableOpacity>
)
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
)
}
return (
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => index}
onPress={this.onPressItem}
/>
</View>
);
}
}
Problem in your code is, that you are calling same method from two sides - on one side you are passing arguments in it on another side you are not passing arguments. If you wan't to have both cases covered you should change you onPressFunction, to accept arguments - in your case item:
onPressItem = (item) => {
navigate('SpeakersClick')
};
try to put this.onPressItem = this.onPressItem.bind(this) on constructor(props)

Call function on another file JS React Native

I have a Parent Class and Child Class but however i can't call a function on Parent Class from Child Class
It just for close the Modal and send a few data from Sorting on my modal. Sorry im a newbie on RN
On OrderScreen i want to separate a modal and screen, so i call modal on another file JS, then on ModalSort.js i want to call back that function has been on his Parents or Order.screen.js
so many way i try but that modal still can't close, if i put onBackdropPress={() => ()} the modal can be close but no respon that i got
Order.screen.js (a.k.a Parents.js)
class OrderScreen extends Component {
constructor(props) {
super(props);
this.state = {
visibleModal: null,
};
};
exit = () => this.setState({ visibleModal: false });
_applySort = () => {
this.setState({ visibleModal: false });
this.onRefresh();
};
pressSort = () => this.setState({ visibleModal: 4 });
render() {
return (
<View style={styles.containerTop}>
<Modal isVisible={this.state.visibleModal === 5} style={styles.bottomModal}>
{this._renderModal()}
</Modal>
<Modal isVisible={this.state.visibleModal === 4}
style={styles.bottomModal} onBackdropPress={() => {this.toggleModal();}}>
{this._renderModalSort()}
</Modal>
<Modal isVisible={this.state.visibleModal === 3} style={styles.bottomModal}>
{this._renderModalFilter()}
</Modal>
<Modal isVisible={this.state.visibleModal === 2} style={styles.bottomModal}>
{this._renderModalEmail()}
</Modal>
<NavigationEvents
onWillFocus={this.willFocusAction} />
<GeneralStatusBarColor backgroundColor="#FFF" barStyle="light-content" />
</View>
)
};
_renderModalSort = () => {
return (
<ModalSort
exit={() => {
this.exit.bind(this);
}}
/>
)
};
const mapStateToProps = ({ authOrder }) => {
const { orderSummary, error, loading, loadingSummary, loadingEmail, typeOfLocation, openNext, openList, closedList, closedNext } = authOrder;
return { orderSummary, error, loading, loadingSummary, loadingEmail, typeOfLocation, openNext, openList, closedList, closedNext };
};
export default connect(mapStateToProps, { getOrderSummary, getOpenOrderList, getClosedOrderList, sendEmailCsvAllOrder, logoutSession })(OrderScreen);
ModalSort.js (a.k.a Child.js)
class ModalSort extends Component {
constructor(props) {
super(props);
this.state = {
visibleModal: null,
}
};
sorter = (isi) => this.setState({ sorted: isi });
_applySort = () => {
this.setState({ visibleModal: false });
// this.onRefresh();
};
render() {
return(
<View style={styles.modalContentSort}>
<View style={styles.modalCenter}>
<View style={styles.headerModel}>
<View style={styles.headerBack}>
<TouchableOpacity onPress={()=>{this.props.exit()}}>
{/* <NavigationEvents onWillFocus={this.willFocusAction} /> */}
<Image style={styles.logoClose} source={require('../../assets/icons/iconClose.png')} />
</TouchableOpacity>
</View>
<View style={styles.headerSort}>
<Text style={styles.textFilter}>Sort by</Text>
</View>
</View>
<Text style={styles.textFilter}>SO Number</Text>
<View style={styles.headerModel}>
<View style={styles.headerFilterItem}>
<TouchableOpacity onPress={() => this.sorter(1)}>
<Text style={this.state.sorted == 1 ? styles.headerBorderItemActive : styles.headerBorderItem}>
<Image style={styles.imageSort} source={require('../../assets/icons/iconNumberAscending.png')} />Ascending</Text>
</TouchableOpacity>
</View>
<View style={styles.headerFilterItem}>
<TouchableOpacity onPress={() => this.sorter(2)}>
<Text style={this.state.sorted == 2 ? styles.headerBorderItemActive : styles.headerBorderItem}>
<Image style={styles.imageSort} source={require('../../assets/icons/iconNumberDescending.png')} />Descending</Text>
</TouchableOpacity>
</View>
</View>
<Text style={styles.textFilter}>PO Customer</Text>
<View style={styles.headerModel}>
<View style={styles.headerFilterItem}>
<TouchableOpacity onPress={() => this.sorter(3)}>
<Text style={this.state.sorted == 3 ? styles.headerBorderItemActive : styles.headerBorderItem}>
<Image style={styles.imageSort} source={require('../../assets/icons/iconNumberAscending.png')} />Ascending</Text>
</TouchableOpacity>
</View>
<View style={styles.headerFilterItem}>
<TouchableOpacity onPress={() => this.sorter(4)}>
<Text style={this.state.sorted == 4 ? styles.headerBorderItemActive : styles.headerBorderItem}>
<Image style={styles.imageSort} source={require('../../assets/icons/iconNumberDescending.png')} />Descending</Text>
</TouchableOpacity>
</View>
</View>
<Text style={styles.textFilter}>SO Date</Text>
<View style={styles.headerModel}>
<TouchableOpacity onPress={() => this.sorter(6)}>
<View style={styles.headerFilterItem}>
<Text style={this.state.sorted == 6 ? styles.headerBorderItemActive : styles.headerBorderItem}>Newest</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.sorter(5)}>
<View style={styles.headerFilterItem}>
<Text style={this.state.sorted == 5 ? styles.headerBorderItemActive : styles.headerBorderItem}>Oldest</Text>
</View>
</TouchableOpacity>
</View>
<Text style={styles.textFilter}>ETA</Text>
<View style={styles.headerModel}>
<TouchableOpacity onPress={() => this.sorter(8)}>
<View style={styles.headerFilterItem}>
<Text style={this.state.sorted == 8 ? styles.headerBorderItemActive : styles.headerBorderItem}>Newest</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={() => this.sorter(7)}>
<View style={styles.headerFilterItem}>
<Text style={this.state.sorted == 7 ? styles.headerBorderItemActive : styles.headerBorderItem}>Oldest</Text>
</View>
</TouchableOpacity>
</View>
<TouchableHighlight style={styles.buttonSort} onPress={this._applySort.bind(this)} >
<Text style={styles.textApply}>Apply</Text>
</TouchableHighlight>
</View>
</View>
)
};
}
export default ModalSort;
Close modal in Parent component from Child component:
Your Order.screen.js has a mistake that make your program wouldn't run properly. When you use this.exit.bind(this);, it will return a callback, not a function. So, when you call this.props.exit() in ModalSort.js, it will call exit that actually shows nothing. To resolve this, you have 2 ways:
Order.screen.js
_renderModalSort = () => {
return (
<ModalSort
exit={this.exit.bind(this)}
/>
)
};
or
_renderModalSort = () => {
return (
<ModalSort
exit={() => {
this.exit();
}}
/>
)
};
Send data from sorting modal:
Since you're using Redux, I suggest you create 2 actions. First action is to save your data to your state tree. Second one is to get those data. If you're not good at Redux, or you don't want to use it, you can try these step:
Initialize a variable to hold your data in Parent:
class OrderScreen extends Component {
constructor(props) {
super(props);
this.state = {
visibleModal: null,
};
this.data = null; // Your data goes here.
/*
You can store your data in state if you want to re-render when updating your data.
this.state = {
visibleModal: null,
data: null
}
*/
}
}
Create a function that save your data in Parent:
saveData(data) {
this.data = data;
}
Pass that function to Child:
_renderModalSort = () => {
return (
<ModalSort
exit={() => {
this.exit();
}}
saveData={(data) => {
this.saveData(data);
}}
/>
)
};
Lastly, you can call it from Child:
class ModalSort extends Component {
sorting() {
data = null; // Your data will be stored in this variable
// You sorting function goes here
this.props.saveData(data); // Save your data
}
}
In case you have other works to do with saved data, you can modify the saveData(data) function in Parent.
Hope this will help you!

React Native FlatList Touchable Opacity

I used FlatList to display the title that is in the data. I added in TouchableOpacity for the FlatList. So for example, when I click 'First', I want to show the the data from 'mood' and it will show the list of passionate,rousing and confident. I want to show the list on a new file/screen and show purely the mood of list.
This is my data:
const Mock =
[
{ title: 'First',
mood:
[
{name: 'passionate'},
{name: 'rousing'},
{name: 'confident'},
],
},
{ title: 'Second',
mood:
[
{name: 'rollicking'},
{name: 'cheerful'},
{name: 'fun'},
{name: 'sweet'},
{name: 'amiable'},
{name: 'natured'}
],
This is my FlatList code:
export default class Cluster1 extends Component{
render() {
return (
<View>
<FlatList
data={Mock}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
What should I do with the TouchableOpacity when I want to show the mood name when I click the title?
This is my style code
const styles = StyleSheet.create({
itemTitle:{
fontSize: 25,
fontWeight: 'bold',
color: 'white',
margin: 20,
},
},
list:{
flex: 1,
backgroundColor: '#00BCD4',
alignItems: 'center',
justifyContent: 'space-between',
flexDirection: 'row',
},
});
You should modify your code as below to do this:
export default class Cluster1 extends Component {
render() {
return (
<View style={{ margin: 30, backgroundColor: '#ddd' }}>
<FlatList
data={Mock}
renderItem={({ item, index }) => {
return <FlatListItem item={item} index={index} />;
}}
/>
</View>
);
}
}
class FlatListItem extends Component {
state = { showItemIndex: [false, false] };
_onPress = index => () => {
let showItemIndex = this.state.showItemIndex;
showItemIndex[index] = !this.state.showItemIndex[index];
this.setState({ showItemIndex });
};
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity onPress={this._onPress(this.props.index)}>
<Text style={styles.itemTitle}>{this.props.item.title}</Text>
</TouchableOpacity>
{this.state.showItemIndex[this.props.index] && (
<FlatList
data={this.props.item.mood}
extraData={this.state.showItemIndex}
renderItem={({ item, index }) => {
return (
<Text item={item} index={index}>
{item.name}
</Text>
);
}}
/>
)}
</View>
</View>
);
}
}
Use this, it's should be work fine for you:
Link: https://github.com/oblador/react-native-collapsible
Link: https://github.com/naoufal/react-native-accordion
Link: https://github.com/cuiyueshuai/react-native-expandable-section-flatlist
You could set a state variable which gets updated whenever your TouchableOpacity gets pressed. And then you conditionally render the title or the list of mood names:
class FlatListItem extends Component {
constructor(props) {
super(props);
this.state = {collapsed: true}
}
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity
onPress={this.onPress}
>
<Text style={styles.itemTitle}>
{this.props.item.title}
</Text>
</TouchableOpacity>
{this.state.collapsed ?
<View /> :
<View>
{this.props.item.mood.map(mood => <Text>{mood.name}</Text>)}
</View>}
</View>
</View>
);
}
onPress = () => {
this.setState({collapsed: !this.state.collapsed})
}
}
You can do this by separating out the datasource that is required to show in the list.
First to display title: you can do something like this
export default class Cluster1 extends Component {
state = {
data: []
};
componentWillMount() {
const titles = Mock.forEach(data => data.title);
this.setState({
data: titles
});
}
onItemClick = item => {
const itemIndex = Mock.findIndex(data => (
data.title === item
));
const values = Mock[itemIndex].mood;
this.setState({
data: values
});
};
render() {
return (
<View>
<FlatList
data={this.state.data}
renderItem={({ item, index }) => {
return (
<FlatListItem
item={item}
index={index}
onItemClick={this.itemClick}
/>
);
}}
/>
</View>
);
}
}
and then in your FlatlistItem code:
class FlatListItem extends Component {
render() {
return (
<View style={styles.list}>
<View>
<TouchableOpacity onPress={() =>
this.props.onItemClick(this.props.item)
}>
<Text style={styles.itemTitle}>
{
this.props.item.name ?
this.props.item.name : this.props.item
}
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}

AsyncStorage mapping not working

I have code
AsyncStorage.getItem("Friends").then((value) => {
this.setState({"Friends": value});
}).done();
I am trying to show in list using
render() {
return ({
this.state.Friends.map((o,i) => {
<View key={i} style={styles.row}>
<View>
<Text style={styles.app_type_name}>{o.name}</Text>
</View>
</View>
})
})
}
I am getting
error evaluating object 'this.state.Friends'
You render method should looks like :
render() {
const {Friends} = this.state;
return (
<div>
{
Friends && Friends.map((o,i) =>
<View key={i} style={styles.row}>
<View><Text style={styles.app_type_name}>{o.name}</Text></View>
</View>
)
}
</div>
);
}