Reputation: 143
I want to display cards with news from a JSON file. Getting the JSON works fine, but I want to add a onPress event, so I can click the card and navigate to the article.
My card view:
<Card>
<CardItem button onPress={this._OnButtonPress(news.id)}>
<Left>
<Body>
<Text style={styles.cardText}>{news.title}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<Left>
<Icon style={styles.icon} name="chatbubbles" />
<Text>{news.comments} comments</Text>
</Left>
<Right>
<Text>{news.published}</Text>
</Right>
</CardItem>
</Card>
I am trying to pass a variable to the onButtonPress() function
_OnButtonPress(newsID) {
Alert.alert(newsID.toString());
}
To test the onPress event, all I did is alert the parameter.
I don't see anything wrong, but still I got this error
Does anyone know how I can fix this and what Im doing wrong here. Thanks in advance.
Update
My updated class:
import React, { Component } from "react";
import {
Image,
ListView,
StyleSheet,
Text,
View,
Alert
} from 'react-native';
import {
Container,
Header,
Left,
Right,
Button,
Card,
CardItem,
Icon,
Body,
Content,
Logo
} from 'native-base';
import styles from "./styles";
const logo = require("../../../img/f1today.png");
var REQUEST_URL = 'http://v2.first-place.nl/test/news.json';
class News extends Component {
constructor(props) {
super(props);
this._OnButtonPress = this._OnButtonPress.bind(this);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
_OnButtonPress(newsID) {
Alert.alert(newsID.toString());
}
componentDidMount() {
this.fetchData();
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData.articles),
loaded: true,
});
})
.done();
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<Container style={styles.container}>
<Header
style={{ backgroundColor: "#fff" }}
androidStatusBarColor="#f05423"
iosBarStyle="light-content">
<Left>
<Button
transparent
onPress={() => this.props.navigation.navigate("DrawerOpen")}
>
<Icon name="ios-menu" style={{color: 'black'}} />
</Button>
</Left>
<Body>
<Image source={logo} style={styles.headerLogo} />
</Body>
<Right />
</Header>
<Content padder>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderNews}
style={styles.listView}
/>
</Content>
</Container>
);
}
renderLoadingView() {
return (
<View style={styles.loading}>
<Text>
Loading news...
</Text>
</View>
);
}
renderNews(news) {
return (
<Card>
<CardItem button onPress={()=> this._OnButtonPress(news.id)}>
<Left>
<Body>
<Text style={styles.cardText}>{news.title}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<Left>
<Icon style={styles.icon} name="chatbubbles" />
<Text>{news.comments} comments</Text>
</Left>
<Right>
<Text>{news.published}</Text>
</Right>
</CardItem>
</Card>
);
}
}
export default News;
Upvotes: 7
Views: 16348
Reputation: 316
You should wrap your CardItem with TouchableOpacity or any other Touchable item. And give onPress function to that Touchable item.
<TouchableOpacity onPress={() => //your function}
<CardItem>
</CardItem>
</TouchableOpacity>
Note: Make sure you use the <TouchableOpacity>
component associated with the react-native
package rather than the react-native-gesture-handler
package. Visual Studio Code editor may auto-import from react-native-gesture-handler
which does not work in this particular use case.
Correct Package:
import { TouchableOpacity } from 'react-native';
Incorrect Package:
import { TouchableOpacity } from 'react-native-gesture-handler';
Upvotes: 12
Reputation: 728
For me i left the button={true} prop off, when i added it works. See example below.
<CardItem
button={true}
onPress={() => {this.cardSelected(item.name)}}
style={{paddingTop:0,paddingBottom:0,paddingLeft:0,paddingRight:0}}>
<Image source={item.img} style={{flex:1,resizeMode: 'cover',height: 175}} />
<Text style={styles.cardheading}>{item.name}</Text>
<Image source={cardline} style={styles.cardline}/>
<Text style={styles.cardtext}> {item.text}</Text>
</CardItem>
Upvotes: 4
Reputation: 1247
The problem you are having is that the method cannot access the scope of the view. Right now you have your renderNews method defined this way:
renderNews(news) { }
If you declare your method this way you will not have this available on your method and as "this" is undefined, all the methods will trigger an error because you are trying to access to "undefined.methodName()". Having said that, you should "tie" the context to your method declaring it this way:
renderNews = (news) => { }
Now you have the context attached to the method and "this" is accesible inside.
Upvotes: 1
Reputation: 971
You need to bind this function. Write the following code inside your constructor function:
this._OnButtonPress = this._OnButtonPress.bind(this);
Also, changed the onPress as following:
onPress={()=> this._OnButtonPress(news.title)}
Finally, i could see the onPress been written on the component. Rather you should define/write it inside that container.
Upvotes: 1