undefined is not an object (evaluating 'this.onPress.bind') - reactjs

Gist: Dashboard.js
I am creating an iOS application with React-Native, I get this error when my Dashboard.js is rendered.
My Dashboard.js renders different scrollableTabView's which each contain a ListView, I have included some code from one list item below.
renderArchiveOrder(order) {
return (
<TouchableHighlight onPress={this.onPress.bind(order.id)}>
<View style={styles.listObject}>
<View style={styles.thumbnail}>
<Text style={styles.title}>#{order.bid}</Text>
<Text style={styles.time}>TID</Text>
<Text style={styles.subTime}>{order.time}</Text>
</View>
<View style={styles.information}>
<Text style={styles.restaurantName}>{title}</Text>
<Text style={styles.dropoffName>{order.locations.dropoff.address}</Text>
</View>
</View>
</TouchableHighlight>
);
}
My problem is that when Dashboard.js is rendered, the app crashes and the included screenshot is being shown.
It clearly states that renderArchiveOrder: Dashboard.js # 364:0 is throwing an error, here's my onPress function.
I can't understand my error is line 364, and why my TouchableHighlight onPress doesn't work.
id: index is line 364.
onPress = (index) => {
this.props.navigator.push({
title: 'Order',
component: Order,
passProps: {
id: index
}
})
};
Why does this occur when I'm just trying to send data to a click function and push the navigator to a new view?

Since you're passing your renderArchiveOrder method as a value to another component, it loses its context. Thus, the this variable inside your method will not refer to your component instance, and trying to access this.onPress will yield undefined.
To fix this, simply bind your method to your component instance before passing it to your ListView component:
<ListView
dataSource={this.state.archiveDataSource}
renderRow={this.renderArchiveOrder.bind(this)}
style={styles.listView}/>

Related

How do I execute a function within a touchable opacity within a flatlist in React Native?

Each item within my flat list is a touchable opacity (an icon). I would like a function to execute when an icon is tapped. This function has been passed as a prop from the parent component and I'm passing the icon data into that prop. I thought this would be straight forward. However when I tap on the icon to open the modal that contains my flat list, the modal doesn't open and I get a warning: 'Cannot update a component from inside the function body of a different component.' I'm confused because I'm executing a function that has been passed as a prop from my parent component. I'm unsure how else I am supposed to do it?
This is the function I want to call on tap (the changeIcon prop is the one causing the issues):
function chosenIcon(selectedIcon) {
props.changeIcon(selectedIcon);
props.closeIconList(false);
}
This is the FlatList, and it doesn't seem to like me passing item.item.icon.
<FlatList
numColumns={3}
data={ICONS}
renderItem={(item) => (
<TouchableOpacity style={styles.item} onPress={chosenIcon(item.item.icon)}>
<Text style={styles.text}>{item.item.icon}</Text>
</TouchableOpacity>
)}
/>
If I comment out the props.changeIcon line in the function and don't pass the data item.item.icon, everything works fine and the modal closes when I select an icon.
I hope that's clear enough! Thank you!
Please try to add a fat arrow function to TouchableOpacity onPress callback.
<FlatList
numColumns = {3}
data = {ICONS}
renderItem = {item => (
<TouchableOpacity style = {styles.item} onPress= {()=> chosenIcon(item.item.icon)}> // add ()=>
<Text style = {styles.text}>{item.item.icon}</Text>
</TouchableOpacity>
)}
/>

onPress of TouchableOpacity gets called when loading Flatlist

I have a flatlist with a search function. In the next step, I want something to happen when I press within the item. I'm facing the problem that the TouchableOpacity is visible, but nothing happens when it's pressed. I've tried the same with a Button and face the same issue.
Instead of onPress being called when something is pressed, it somehow get's called once the screen loads immediately. If I for example console.log(item.title) I get all the titles in my console log that are currently in the flatlist.
I've tried to figure out what is causing this for many hours, but can't seem to find any reason. Any help is highly appreciated.
I have a Flatlist that is populated with data, set up as follows:
return (
<View style={styles.list}>
<FlatList
data = {this.state.data}
renderItem={renderListItem}
keyExtractor={item => item.id}
ListHeaderComponent={this.renderHeader}
/>
</View>
);
}
}
const renderListItem = (item) => {
return (
<MyTouchable
id={item.item.id}
title={item.item.title}
/>
);
}
MyTouchable Component looks like this:
<View>
<TouchableOpacity onPress={console.log("Pressed")}>
<View style={styles.mainView}>
<View>
<Text style={styles.text}>{props.id} {props.title}</Text>
</View>
</View>
</TouchableOpacity>
</View>
Try to pass the console.log inside an arrow function
<TouchableOpacity onPress={() => console.log("Pressed")}>
...
</TouchableOpacity>
You can’t write like this: <Component makeThing={myFunc()} />. You should write like that: <Component makeThing={() => myFunc()} /> if you are not using useCallback.
Make sure to read the docs about passing functions to components.
You must provide and arrow function, and call your function inside it.
Or just use useCallback hook:
const Component = () => {
const myFunction = useCallback(() => {
// do something
}, []);
return <AnotherComponent coolFunction={myFunction} />
}

React Native Component not re-rendering despite render function running

I am a little baffled here ..
I have some code like this
renderTopic(topic){
if(topic.isMine){console.log('work?')}
return (
<View key={topic.id.toString()} >
<TouchableOpacity onPress={() => this.addToic.call(this, topic)} >
{topic.isMine && <Topic topic={topic} active={true}/>}
{!topic.isMine && <Topic topic={topic} active={false}/>}
</TouchableOpacity>
</View>
)
}
render() {
console.log("re-rendering", this.props.myTopics)
return (
<View style={s.welcome}>
<ScrollView>
<View style={s.topics}>
{this.props.me.myTopics.map(topic => this.renderTopic(topic) )}
</View>
</ScrollView>
</View>
)
}
The problem is when I update topics using the traditional redux -> 'dispatch action' method, the re-render function fires, the should component update function fires, everything looks like it works but the topic.isMine conditional rendering never updates and switches the components over.
The correct result is displayed if I change page, the app then re-renders correctly.
Probably your reducer does not create new topic object. React sees, that reference to new topic matches old topic and skips calling renderTopic(topic) with same reference value as before.

How can I create a modal and render it on the fly?

I am building my first app in React Native, I have a ListView that displays a number of items and each one is clickable. My question is when I click on a row I would like a modal to appear above. Similar in IOS to clicking and the adding a subview.
renderRow( rowData ){
return (
<TouchableHighlight onPress={() => this.pressRow()}>
<View style={styles.parcelInfoContainer}>
</View>
</TouchableHighlight>
);
}
Now the problem is I am unsure about what to do in the function called by pressRow in relation to rendering the new component. In IOS I would simply add the view at this point but I am not sure how to go about it in React Native. I understand the idea of components just not how to render a new component on the fly.
If you're going to render the same Modal, in terms of layout, you should define it in render() function. Rendering on the fly is not possible, but you can change the states to make modal show what you like.
onPressRow = (dataFromRow) => {
this.setState({
modalText: dataFromRow.text
})
this.showModal(); //Call your function to show modal
}
render() {
return (
<View>
<FlatList />
<Modal>
<View>
...
<Text>{this.state.modalText}</Text>
</View>
</Modal>
</View>
)
}
However, if you want different layout for each row, you should write a this.getModalContent() like function to determine which layout should be rendered. You should call this function in render => <Modal> {this.getModalContent()} </Modal>
getModalContent = () => {
switch (this.state.modalText) { // define a better logic here.
case 'a':
return ( <Text> hey </Text>)
...
}
}

How to add a button in react native environment?

could you please tell me how to add button in view using react native .
here is my code
https://rnplay.org/apps/0TPePA
can I used this this
https://npmcdn.com/react-native-button#1.6.0
in my demo ?
I need to add button in my view here is code
class First extends Component {
render (){
return (<View><Text>"hello"</Text>
</View>
)
}
}
Creating a button yourself is quite simple. You can use toucableopacity and the onPress method attached to it.
Put the following in your render method
<TouchableOpacity onPress={this._onButtonPress}>
<Text>Button Text</Text>
</TouchableOpacity>
And put this in a react function.
_onButtonPress: function () {
console.log ("Button has been pressed");
}
To make it look more like a button you can add styling directly to the <Text style={{flex: 1, backgroundColor: 'blue', etc...}}

Resources