Description
I'm dealing with a JSON response in React Native that's coming from the WordPress REST API, containing pages with each an (profile page) ID, title and featured image.
Using a FlatList, I have created a screen with featured images and titles for each (Artist) page. I want to add the functionality to navigate to each individual page by clicking on an item in the FlatList, and passing the title, featured image and (later) the content of the regarding page to the next screen to display this information (probably based on the ID).
LinksScreen.js
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Artist from './Artist';
import { createStackNavigator } from 'react-navigation';
import {
ScrollView,
StyleSheet,
View,
Text,
Image,
FlatList,
ActivityIndicator,
TouchableHighlight,
} from 'react-native';
export default class LinksScreen extends React.Component {
constructor(props) {
super(props);
this._onAlertTypePressed = this._onAlertTypePressed.bind(this);
this.state = {
data: [],
}
}
_onAlertTypePressed(typeId: any, typeName: any, imageUrl: any){
this.props.navigator.push({
screen: 'Artist',
title: 'Artist',
passProps: {
alertId: typeId,
alertName: typeName,
alertImage: imageUrl,
}
});
}
_renderListItem = ({ item }) => (
<Artist
itemName={ item.title.rendered }
itemId={ item.id }
itemImageUrl={ item.better_featured_image.source_url}
onPressItem={ this._onAlertTypePressed }
/>
);
static navigationOptions = {
title: 'Links',
};
state = {
data: [],
isLoading: true,
isError: false,
};
static propTypes = {
navigation: PropTypes.shape({
navigate: PropTypes.func.isRequired,
}).isRequired,
}
componentWillMount() {
fetch('http://54.168.73.151/wp-json/wp/v2/pages?parent=38&per_page=100')
.then(response => response.json())
.then((responseJson) => {
responseJson.sort((a, b) => a.title.rendered < b.title.rendered ? -1 : 1);
this.setState({
data: responseJson,
isLoading: false,
isError: false,
});
})
.catch(error => {
this.setState({
isLoading: false,
isError: true,
});
console.error(error);
});
}
renderRow = item => (
<View style={styles.grid}>
<Image
style={styles.thumb}
source={{
uri: item.better_featured_image
? item.better_featured_image.source_url
: 'http://54.168.73.151/wp-content/uploads/2018/04/brand-logo.jpg',
}}
/>
<Text style={styles.title}>{item.title.rendered}</Text>
</View>
);
getKey = item => String(item.id);
renderComponent() {
if (this.state.isLoading) {
return <ActivityIndicator />;
} else if (this.state.isError) {
return <Text>Error loading data</Text>;
} else {
return (
<FlatList
numColumns={3}
contentContainerStyle={styles.elementsContainer}
data={this.state.data}
renderItem={({ item }) => this._renderListItem}
keyExtractor={this.getKey}
/>
);
}
}
render() {
return (
<View style={styles.container}>
<Text
style={{
fontSize: 20,
color: '#FFFFFF',
marginLeft: 4,
marginTop: 10,
}}>
RESIDENTS
</Text>
{this.renderComponent()}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#000000',
},
elementsContainer: {
backgroundColor: '#000000',
},
grid: {
marginTop: 15,
marginBottom: 15,
marginLeft: 5,
height: 125,
width: 115,
borderBottomWidth: 1,
borderBottomColor: '#191970',
},
title: {
color: '#FFFFFF',
textAlign: 'left',
fontSize: 12,
},
thumb: {
height: 110,
width: 110,
resizeMode: 'cover',
},
});
Artist.js
import React, { Component } from 'react';
import { createStackNavigator } from 'react-navigation';
import {
ScrollView,
StyleSheet,
View,
Text,
TouchableOpacity,
Image,
} from 'react-native';
export class Artist extends React.PureComponent {
constructor(props) {
super(props);
}
_onPress = () => {
this.props.onPressItem(
String(this.props.itemId),
String(this.props.itemName),
String(this.props.itemImageUrl)
);
};
static navigationOptions = {
title: 'Artist',
};
render() {
// const artist = this.props.navigation.state.params.artist;
return (
<TouchableOpacity
{...this.props}
style={styles.container}
onPress={this._onPress}>
<Image
style={styles.image}
source={{
uri: this.props.itemImageUrl
? this.props.itemImageUrl
: 'http://54.168.73.151/wp-content/uploads/2018/04/brand-logo.jpg',
}}
/>
<Text style={styles.title}>{this.props.itemName}</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#000000',
},
title: {
color: '#FFFFFF',
textAlign: 'left',
fontSize: 12,
},
image: {
height: 350,
width: 350,
resizeMode: 'cover',
},
});
I'm getting an error at the moment - saying that the a string is expected, but an undefined type was found. I used to do it in a different way, but I'm unable to pass the ID (which should be the identifier to pass the data to the next screen) to open a specific generated screen for each artist.
Error:
Here is the edible code:
https://snack.expo.io/@jvdl2711/artist-navigation
It used to be like this:
https://snack.expo.io/@jvdl2711/artists (working grid version, but no navigation functionality. I'm sure it gives a good indication of how it's supposed to work.)
Notes
Please, don't mind the titles at the moment. I still have a small unsolved issue regarding unicodes, but I think this won't matter when passing the titles to another screen.