I'm getting the error "this2. is not a function"
I tried a few solution i found on google but still cant fun a way to call the function.
My main purpose is to call a action function in a action file. Had some issues so i plan to call a function first then try call that action.
viewJob(){
console.log("View");
}
renderItem({ item }) {
return(
<Card>
<View style={{height:300}}>
</View>
<View style={styles.detailWrapper}>
<Button
title="Apply"
onPress={() => this.viewJob()}
/>
</View>
</Card>
);
}
Update
render(){
return(
<View style={{ marginTop:10 }}>
<FlatList
contentContainerStyle={styles.list}
data={this.props.jobs}
keyExtractor={this._keyExtractor}
renderItem={this.renderItem.bind(this)} // I didnt bind this , which led to the error above
/>
</View>
);
}
You need to bind the method
render(){
return(
<View style={{ marginTop:10 }}>
<FlatList
contentContainerStyle={styles.list}
data={this.props.jobs}
keyExtractor={this._keyExtractor}
renderItem={this.renderItem.bind(this)}
/>
</View>
);
}
Note: if you use arrow function then you do not have to worry about binding
You can read more about when to bind from official doc
Related
Below in a code I have describe the question as comment
//This is MessagesScreen.js
<FlatList
data={messages}
keyExtractor={messages => messages.id.toString()}
renderItem={({ item }) =>
<ListItem style={styles.listItem}
title={item.title}
subTitle={item.description}
image={item.image}
DeleteIconView={ListItemDeleteAction} /*Here ListItemDeleteAction.js
is component want to pass it to
the ListItem.js. Note: I have
imported all the nessory
labries*/
onPress={() => handleDelete(item)}
//renderRightActions={ListItemDeleteAction}
/>
}
ItemSeparatorComponent={ListItemSeparator}
refreshing={refreshing}
onRefresh={() => {
setMessages([
{
id: 2,
title: 'Komail',
description: 'React-Native Developer',
image: require("../asserts/komail.jpg"),
}
])
}}
/>
This is ListItemDeleteAction.js, which I want to render in ItemList.js
//This is ListItemDeleteAction.js
function ListItemDeleteAction(props) {
return (
<View style={styles.container}>
<MaterialCommunityIcons name="trash-can" size={30} color={Colors.danger} />
</View>
);
}
Now, in ListItem.js I want to render the ListItemDeleteAction.js as I have passed as a argument. Below in code I have described as comment.
Note: I am strict to this method, render the ListItemDeleteAction as it passed as argument, which is "DeleteIconView" as parameter in ListItem.js
function ListItem({ image, title, subTitle, ImageComponent, style, onPress, DeleteIconView}) {
return (
<TouchableHighlight
//onPress={onPress}
underlayColor={Colors.light}
>
<View style={[styles.container, style]}>
{ImageComponent}
{image && <Image style={styles.image} source={image} />}
<View style={styles.parentDeatailContainer}>
<View style={styles.detailContainer}>
<Text style={{ fontWeight: "bold" }}>{title}</Text>
{subTitle && <Text>{subTitle}</Text>}
</View>
<TouchableOpacity style={styles.deleteIconContainer} onPress={onPress}>
{DeleteIconView} /* This is the place where I want to render the
ListItemDeleteAction components as I passed as argument but How? */
</TouchableOpacity>
</View>
</View>
</TouchableHighlight>
);
}
You are passing the prop wrong. When you write DeleteIconView={ListItemDeleteAction}, you aren't actually creating a JSX component. This can be solved by writing the following.
renderItem={({ item }) =>
<ListItem style={styles.listItem}
title={item.title}
subTitle={item.description}
image={item.image}
DeleteIconView={<ListItemDeleteAction />}
onPress={() => handleDelete(item)}
/>
}
Now, the prop DeleteIconView is an actual JSX component which can be rendered as usual.
I've been trying to use Tap Gesture Handler in my React Native project but I'm facing some problem with nested gestures. I've one parent TapGestureHandler(let's call it A) and and child TapGestureHandler(let's call it B). When I click on B then A is also getting executed. Please help me to solve this problem.
Here's my code for TapGestureHandler A:
<TapGestureHandler
ref={ref}
onHandlerStateChange={() => console.log("1")}>
<Animated.View>
<View style={styles.container}>
<View style={styles.leftContainer}>
<ProfilePic image={user.image} />
</View>
<View style={styles.rightContainer}>
<PostCardHeader user={user} />
<Discription discription={discription} />
<View style={styles.gridContainer}>
<ImageGrid waitFor={ref} images={attachedfiles} />
</View>
<Footer />
</View>
</View>
</Animated.View>
</TapGestureHandler>
Here's my code for TapGestureHandler B:
const ImageGrid = ({waitFor}) => {
return (
<TapGestureHandler
waitFor={waitFor || undefined}
onHandlerStateChange={() => console.log("2")}>
<Animated.View style={{ flex: 1 }}>
<Image
style={styles.image}
source={images[0]} />
</Animated.View>
</TapGestureHandler>
)
}
I've tried several times with , but didn't work. Maybe I don't know where to put it in code. I'm a beginner in react-native, but I need your help. Please share your answers!
render() {
console.log('render register -> renderComponent');
return (
<View style={styles.container}>
<Image source={require('../components/logo.png')} />
<KeyboardAvoidingView style={styles_register.containerView} behavior="padding">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles_register.registerScreenContainer}>
<View style={styles_register.registerFormView}>
<ThemeProvider theme={theme}>
<Button
buttonStyle={styles.loginButtonn}
onPress={() => {
this.registerWithFacebook();
}}
title = "Login with Facebook"
/>
</ThemeProvider>
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
</View>
);
}
}
First of all, make sure that your image is in that path ../components/logo.png, also set the size to your image component. Since you are beginner always start with the documentation
<Image
style={{width: 50, height: 50}}
source={require('../components/logo.png')}
/>
render() {
console.log('render register -> renderComponent');
return (
I know there are already so many queries on this topic, I have tried every step but still won't be able to fix the issue.
Here is the code :
render() {
const {sContainer, sSearchBar} = styles;
if (this.props.InviteState.objectForDeleteList){
this.updateList(this.props.InviteState.objectForDeleteList);
}
return (
<View style={styles.mainContainer}>
<CustomNavBar
onBackPress={() => this.props.navigation.goBack()}
/>
<View
style={sContainer}
>
<ScrollView keyboardShouldPersistTaps="always">
<TextInput
underlineColorAndroid={'transparent'}
placeholder={'Search'}
placeholderTextColor={'white'}
selectionColor={Color.colorPrimaryDark}
style={sSearchBar}
onChangeText={(searchTerm) => this.setState({searchTerm})}
/>
</ScrollView>
{this.renderInviteUserList()}
</View>
</View>
);
}
renderInviteUserList() {
if (this.props.InviteState.inviteUsers.length > 0) {
return (
<SearchableFlatlist
searchProperty={'fullName'}
searchTerm={this.state.searchTerm}
data={this.props.InviteState.inviteUsers}
containerStyle={styles.listStyle}
renderItem={({item}) => this.renderItem(item)}
keyExtractor={(item) => item.id}
/>
);
}
return (
<View style={styles.emptyListContainer}>
<Text style={styles.noUserFoundText}>
{this.props.InviteState.noInviteUserFound}
</Text>
</View>
);
}
renderItem(item) {
return (
this.state.userData && this.state.userData.id !== item.id
?
<TouchableOpacity
style={styles.itemContainer}
onPress={() => this.onSelectUser(item)}>
<View style={styles.itemSubContainer}>
<Avatar
medium
rounded
source={
item.imageUrl === ''
? require('../../assets/user_image.png')
: {uri: item.imageUrl}
}
onPress={() => console.log('Works!')}
activeOpacity={0.7}
/>
<View style={styles.userNameContainer}>
<Text style={styles.userNameText} numberOfLines={1}>
{item.fullName}
</Text>
</View>
<CustomButton
style={{
flexWrap: 'wrap',
alignSelf: 'flex-end',
marginTop: 10,
marginBottom: 10,
width: 90,
}}
showIcon={false}
btnText={'Add'}
onPress={() => this.onClickSendInvitation(item)}
/>
</View>
</TouchableOpacity> : null
);
}
**I even tried with bellow code as suggested by #Nirmalsinh **:
<ScrollView keyboardShouldPersistTaps="always" style={sContainer}>
<CustomNavBar
onBackPress={() => this.props.navigation.goBack()}
/>
<TextInput underlineColorAndroid={'transparent'}
placeholder={'Search'}
placeholderTextColor={'white'}
selectionColor={Color.colorPrimaryDark}
style={sSearchBar}
onChangeText={(searchTerm) => this.setState({searchTerm})} />
{this.renderInviteUserList()}
</ScrollView>
I have followed this article:
https://medium.com/react-native-training/todays-react-native-tip-keyboard-issues-in-scrollview-8cfbeb92995b
I have tried with keyboardShouldPersistTaps=handled also but still, I have to tap twice on my Custom Button to perform an action. Can anybody tell me what I am doing wrong inside the code?
Thanks.
You need to add give value always in keyboardShouldPersistTaps to allow user tap without closing the keyboard.
keyboardShouldPersistTaps='always'
For example:
<ScrollView keyboardShouldPersistTaps='always'>
// Put your component
</ScrollView>
NOTE: Kindly put your tappable component inside the ScrollView. Otherwise it won't work.
You can use keyboardShouldPersistTaps='handled' in a ScrollView or Scrollables like FlatList SectionList etc. and embed a TouchableWithoutFeedBack to handle the case for dismiss on outside clicks.
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<ScrollView keyboardShouldPersistTaps='handled'>
// Rest of the content.
</ScrollView/>
</TouchableWithoutFeedback>
For FlatList and SectionList you will have to handle KeyBoard.dismiss separately.
Please try this, It's working for me, it will works you also, i hope it helps...
I'm trying to create custom button. For this, I wrapped my existed view into TouchableHighlight (write me please another way, if it's not suitable here)
<TouchableHighlight onPress={this.freeTimeTapped} underlayColor="white">
<LabelsView data={this.freeTimeData}
containerStyle={{ backgroundColor: '#3A65FF' }} />
</TouchableHighlight>
This code throws an error touchable child must either be native, described here, for example. So, I added
setNativeProps = (nativeProps) => {
this._root.setNativeProps(nativeProps);
}
error disappeared, but now I receive an error
React Native Error: undefined is not an object (evaluating
'_this._root.setNativeProps')
after touch. What am I doing wrong?
More code about LabelsView:
export default class LabelsView extends Component {
// Make TouchableHighlight wrapper work
setNativeProps = (nativeProps) => {
this._root.setNativeProps(nativeProps);
}
render() {
return (
<View style={[styles.container, this.props.containerStyle]}>
<View style={styles.leftContainer}>
<Text style={[styles.nameText, styles.textColor]}> {this.props.data.leftText} </Text>
</View>
<View style={styles.rightContainer}>
<Text style={[styles.durationText, styles.textColor]}> {this.props.data.rightTopText + ' hrs'} </Text>
<Text style={[styles.rangeText, styles.textColor]}> {this.props.data.rightBottomText} </Text>
</View>
</View>
);
}
}
I created the same sitaution as yours and found that the only thing you are doing wrong is you are wrapping a class inside the TouchableHighlight . If you want to wrap it in any touchable component then react native needs the native child, So to resolves this change your code as follows:-
<LabelsView freeTimeTapped={this.freeTimeTapped} data={this.freeTimeData}
containerStyle={{ backgroundColor: '#3A65FF' }} />
and your LabelsView class as follows:-
render() {
return (
<TouchableHighlight onPress={this.props.freeTimeTapped} underlayColor="white">
<View style={[styles.container, this.props.containerStyle]}>
<View style={styles.leftContainer}>
<Text style={[styles.nameText, styles.textColor]}> {this.props.data.leftText} </Text>
</View>
<View style={styles.rightContainer}>
<Text style={[styles.durationText, styles.textColor]}> {this.props.data.rightTopText + ' hrs'} </Text>
<Text style={[styles.rangeText, styles.textColor]}> {this.props.data.rightBottomText} </Text>
</View>
</View>
</TouchableHighlight>
);
}
If you still hava any problem then let me know :)
In case you want to have it in parent, just fix your code to this:
export default class LabelsView extends Component {
// Make TouchableHighlight wrapper work
setNativeProps = (nativeProps) => {
this._root.setNativeProps(nativeProps);
}
render() {
return (
<View ref={component => this._root = component} style={[styles.container, this.props.containerStyle]}>
<View style={styles.leftContainer}>
<Text style={[styles.nameText, styles.textColor]}> {this.props.data.leftText} </Text>
</View>
<View style={styles.rightContainer}>
<Text style={[styles.durationText, styles.textColor]}> {this.props.data.rightTopText + ' hrs'} </Text>
<Text style={[styles.rangeText, styles.textColor]}> {this.props.data.rightBottomText} </Text>
</View>
</View>
);
}
}
You missed ref={component => this._root = component}