<TouchableOpacity
style={{backgroundColor: '#FF00FF'}}
onPress={this.inputField}
>
<UselessTextInput
multiline = {true}
numberOfLines = {4}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</TouchableOpacity>
The function onPress call is:
inputField() {
console.log('Clicked')
}
i can't find any solution y its not working
i tried changing onPress to onPress={() => { console.log('Clicked') }}
it still didn't work
Can anyone tell me y its not working what i m doing wrong in it
try passing an arrowed function to the onClick prop, otherwise it won't be executed when you click on it, there are two different ways which lead to the same result :
first (in the function declaration) :
inputField = () => {
console.log('Clicked')
}
second (in the onPress prop) :
onPress={() => this.inputField}
Try adding () to the this.inputField, like the code:
onPress={()=>{this.inputField()}}
Related
I did a custom select but I have the problem to close it if I press outside the select or options. basically the "button" is a TouchableOpacity and when I click on it there appears the list of options. But now I can close it only by choosing one option or clicking back on the select button. Is there a way to check whether I click outside the TouchableOpacity or not? In simple react you can give an Id to the component and check it onClick event to see what you have clicked. Or you can use react's useRef hook which doesn't seem to work with react-native. I have this code (simplified):
const [isOpen, setIsOpen] = useState(false)
const toggle = () => { setIsOpen(!isOpen)}
//...
return (<View>
<TouchableOpacity onPress={toggle}>
<Text>Open select</Text>
</TouchableOpacity>
<View>
{isOpen && options.map(({value, label}) => <View key={value} onPress={toggle}>{label}</View>)}
</View>
</View>)
As you can see you can call toggle only if you press the select button or an option. I want to call setIsOpen(false) when I click outside the TouchableOpacity box.
Is there a way or library to do it?
First of all correct usage for toggle function is
setIsOpen(prevIsOpen => !prevIsOpen);
And regarding your question. Just wrap all screen into touchable component without any feedback.
const close = () => isOpen && setIsOpen(false);
return (
<TouchableWithoutFeedback onPress={close} style={{ flex: 1 }}>
<View>
<TouchableOpacity onPress={toggle}>
<Text>Open select</Text>
</TouchableOpacity>
<View>
{isOpen && options.map(({value, label}) => <View key={value} onPress={toggle}>{label}</View>)}
</View>
</View>
</TouchableWithoutFeedback>
);
you can use TouchableWithoutFeedback
i had this issue where i'm trying to make sure the parent's onPress is triggered, but it wont
im trying to create a custom touchableOpacity component that able can be reusable, that wrap other Component so it can decide if the children can be shown or not and decide/alter what happen when the children component is pressed.
const CustomTouchable = (children, onPress) => {
function handleOnPress = () => {
if(validation){
onPress();
}
}
return <TouchableOpacity onPress={handleOnPress}>{children}</TouchableOpacity>
}
const MainComponent = () => {
function onPress = () => {console.log('test')}
<CustomTouchable onPress={onPress}>
<TouchableOpacity style={styles.button}>
<Text>Press Here</Text>
</TouchableOpacity>
</CustomTouchable>
}
but the parent onPress is not triggered, how can i trigger it?
This is because the touch event is received by the children and not the parent. Assign following prop to your Child Component
pointerEvents={"none"}
Make the second TouchableOpacity disabled like this
<TouchableOpacity onPress={onPress}>
<TouchableOpacity
disabled
style={styles.button}
>
<Text>Press Here</Text>
</TouchableOpacity>
</TouchableOpacity>
I'm building a React Native app and using the tomb-form-native library for my forms. In one of my screens, I loop through an array of types and output a form for each type:
{my_types.map(ob =>
<View key={++i}>
<Text>{ob.type} #{ob.num}</Text>
<Form
ref={(c) => {
this.form = {}
this.form[ob.type] = c
}}
type={_formType(this, ob.type)}
options={_formOptions(ob.type)}
value={this.state.value}
onChange={this.onChange.bind(this)}
/>
</View>
)}
<TouchableHighlight style={styles.button} onPress={this.onPress.bind(this)}>
<Text style={styles.buttonText}>Submit</Text>
</TouchableHighlight>
But when I try to get the submitted values in my onPress function, it doesn't work for multiple types. It works for one type if I only call getValue() once:
input = this.form['my_type'].getValue()
console.log(input) // I see in my debugger that it works.
But if I try to get the input for two or more types, I don't see anything in the log...
input = this.form['my_type'].getValue()
console.log(input) // Nothing. It doesn't work.
input2 = this.form['my_other_type'].getValue()
console.log(input2) // Nothing here either.
Is it possible to use the tcomb library to submit multiple forms with one onPress? Maybe it's the way I call my onPress function in the onPress property of TouchableHighlight?
UPDATE
This simplified onPress function suggests my form ref is only working the last time through the loop. If my loop has two items...
onPress() {
let input = this.form[1]
console.log(input) // Undefined.
let input2 = this.form[2]
console.log(input2) // Object.
}
It appears to be possible. If I use an array to track the form refs, it works:
this.form = []
return (
...
{a.map(ob =>
<View key={++i} style={s}>
<Text>{ob.type} #{ob.num}</Text>
<Form
ref={(c) => {
this.form.push(c)
}}
key={i}
type={_formType(this, ob.type)}
options={_formOptions(ob.type)}
value={this.state.value}
onChange={this.onChange.bind(this)}
/>
</View>
)}
<TouchableHighlight style={styles.button} onPress={this.onPress.bind(this)}>
<Text style={styles.buttonText}>Submit</Text>
</TouchableHighlight>
And here is a simplified onPress...
onPress() {
let tF = this.form
tF.forEach(function(f) {
if (f) { // First two times through the loop, f is null, in my application.
console.log(f.getValue()) // It works!
}
})
}
I got this code
constructor(props){
super(props);
this.MyClick = this.MyClick.bind(this)
}
MyClick() {
alert('ohoho')
};
AnyRequest = () => {
if(this.state.Array.length > 0 && this.state.Loaded === true){
return this.state.Array.map(function(Data){
return(
<View>
<TouchableHighlight underlayColor="#ccc" onPress={this.MyClick}>
<Icon name="check" size={30} color="#2eb82e" />
</TouchableHighlight>
</View>
);
});
}
};
I have no idea why it doesn't work. First when I used MyClick = () => instead of binding function in the constructor it was saying undefined is not an object. As soon as I bound my function in the constructor it doesn't show error anymore but it doesn't seem like a TouchableHighlight button. Even underlayColor doesn't work.
Ok, so from the comments, we can conclude that this the TouchableHighlight is indeed clickable. It's just your syntax for onPress that is incorrect. This is a very common mistake for developers without much experience in binding and ES6 syntax. There are answers that cover this already so I won't go into depth on it. Instead, I'll point out the two common ways you can correct define onPress in React Native (there are also multiple existing answers for this but they are only partially related):
The onPress prop of TouchableHighlight expects a function to be passed to it. So whatever is between the { } needs to be a function. The first way to do this is with arrow syntax which I suspect you did incorrectly:
MyClick = () => {
alert('ohoho')
};
// ... later on ...
<TouchableHighlight underlayColor="#ccc" onPress={this.MyClick}>
<Icon name="check" size={30} color="#2eb82e" />
</TouchableHighlight>
Note the this. as it's needed to correctly reference the right variable.
The second way is to bind the method as you're doing but then actually call it in a function that you pass to onPress like so:
constructor(props){
super(props);
this.MyClick = this.MyClick.bind(this);
}
MyClick() {
alert('ohoho');
};
// ... later on ...
<TouchableHighlight
underlayColor="#ccc"
onPress={() => {
this.MyClick();
}}
>
<Icon name="check" size={30} color="#2eb82e" />
</TouchableHighlight>
Note how you are defining an arrow function inside the { } and then actually calling MyClick inside that function.
If you don't understand the difference or make many mistakes like this, then I suggest brushing up on ES6 and ES7 as that is almost a requirement for writing React Native code. There are many resources online to help with this.
Finally I got it. Problem wasn't in onPress function but in map function. As soon as I was creating new function it created a new scope which means this wasn't referring to AnyRequest function anymore. Finally ES6 arrows fixed it.
constructor(props){
super(props);
this.MyClick = this.MyClick.bind(this)
}
MyClick() {
alert('ohoho')
};
AnyRequest = () => {
if(this.state.Array.length > 0 && this.state.Loaded === true){
return this.state.Array.map((Data) => (
<View>
<TouchableHighlight underlayColor="#ccc" onPress={() =>
this.MyClick();
}}>
<Icon name="check" size={30} color="#2eb82e" />
</TouchableHighlight>
</View>
));
}
};
The below code works and when clicked takes me the loginStack Stack Navigator
<TouchableWithoutFeedback
onPress={ this.navigateToScreen('loginStack') }>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
My NavigateToScreen function looks like this
navigateToScreen = (route) => () => {
const navigationAction = NavigationActions.navigate({
routeName: route
})
this.props.navigation.dispatch(navigationAction)
}
Since I need to manage multiple stuff, I converted it to an arrow function and it doesn't work. The below code does nothing when pressed. No response at all.
<TouchableWithoutFeedback
onPress={ () => this.navigateToScreen('loginStack') }>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
How do I fix this so I can run multiple lines of code on the onPress function like given below?
<TouchableWithoutFeedback
onPress={ () => { this.navigateToScreen('loginStack')
AsyncStorage.removeItem('token')
}}>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
Your navigateToScreen function is returning another function, which in your working example is the function being called when pressed. Where you changed onPress to an arrow function, you are calling navigateToScreen but not the function it returns.
Changing it to
<TouchableWithoutFeedback
onPress={ () => {
this.navigateToScreen('loginStack')()
AsyncStorage.removeItem('token')
}}>
<View><Text>Click Me</Text></View>
</TouchableWithoutFeedback>
should work, or you could remove the second arrow function in your navigateToScreen function so it no longer returns a function but executes the code itself
navigateToScreen = (route) => {
const navigationAction = NavigationActions.navigate({
routeName: route
})
this.props.navigation.dispatch(navigationAction)
}
I would recommend this option, but keep in mind your currently working example would no longer work in this case.
TouchableWithoutFeedback always needs to have child View component.
<TouchableWithoutFeedback onPress={ this.navigateToScreen('loginStack') }}>
<View>
<Text>Click Me</Text>
</View>
</TouchableWithoutFeedback>