Can a single button do different things? - javascript

I have two buttons to do two actions, is it possible to have only one button that should change the text and the actions that it does?
<TouchableOpacity style={styles.button} onPress={() => this.stopFunction()}>
<Text style={styles.buttonTesto}>STOP</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={() => this.startFunction()}>
<Text style={styles.buttonTesto}>START</Text>
</TouchableOpacity>
So the first time is Start, when the user clicks, the button launch the startFunction and change the text in Stop.

I suppose you have a state variable running
this.state = { running : true }
Now Inside your render method get the state data :
const { running } = this.state
your button should look like this :
<TouchableOpacity style={styles.button} onPress={() => this.uniqueFunction()}>
<Text style={styles.buttonTesto}>
{ running ? 'STOP' : 'START'}
</Text>
</TouchableOpacity>
Now your unique function have to do the two actions depends on application running status:
uniqueFunction = () => {
const { running } = this.state
if( running ) {
// The action you want to do when start button is pressed
}else
// The action you want to do when stop button is pressed
}

You need a state variable, and then you can use conditional rendering based on value of the variable. Like this:
<TouchableOpacity style={styles.button}
onPress={() => {this.state.flag ? this.stopFunction() : this.startFunction()}}
>
<Text style={styles.buttonTesto}>{this.state.flag? "STOP" : "START"}</Text>
</TouchableOpacity>

Related

onChangeText callback function save previous input

iam new in react native
and iam trying to create my first todo list app using react native and js
i faced a problem in validation of this app
iam using a textInput to take the task as input from the user and iam using onchangetext callback function
<TextInput style={styles.input} placeholder={'Write a task'} value={task} onChangeText={text =>{
console.log(text.length)
if(text.length==0){
checkEmpty(true);
setTask(null);
}
else{
checkEmpty(false);
setTask(text);
clearText('');
}
}}/>
and a buttom to create the task
<TouchableOpacity onPress={()=>{
handleAddTask();
}}>
<View style={styles.addWrapper}>
<Text style={styles.addText}>+</Text>
</View>
</TouchableOpacity>
and this is the function handleAddTask
const handleAddTask=()=>{
Keyboard.dismiss();
if(isEmpty==false){
setTaskItems([...taskItems,task])
setTask('');
}
else{
Alert.alert('OOPS!','Todos must contain at least 1 character',[
{text:'Okay', onPress: ()=> console.log('Alert closed')}
]);
setTask('');
}
}
the problem here is that
after the application start for the first time : if i didnt enter any input and press on the TouchableOpacity the alert pop up
and after i enter any input and add a task and add it successfully when i press the TouchableOpacity again when the input is empty it create empty task to solve the problem i must type any character and delete it and press the TouchableOpacity to make the alert pop up again as the input is empty
... i want to know how to solve this validation problem
I tried playing along with your code and I think the isEmpty state isn't working as expected (you didn't expose that part of code either). You can update your checkEmpty after task is updated.
useEffect(() => {
if(task.length) {
checkEmpty(false)
} else {
checkEmpty(true)
}
},[task])
But ,actually you don't need to assign another state to check if the state is empty, you can just use task.length to check.
const [task, setTask] = React.useState('');
const [taskItems, setTaskItems] = React.useState([])
const handleAddTask=()=>{
// Keyboard.dismiss();
if(task){
setTaskItems(prev => [...prev,task])
setTask('');
}
else{
Alert.alert('OOPS!','Todos must contain at least 1 character',[
{text:'Okay', onPress: ()=> console.log('Alert closed')}
]);
// setTask('');
}
}
return (
<View style={styles.container}>
<TextInput
placeholder={'Write a task'}
value={task}
onChangeText={(text) => setTask(text)}
/>
<TouchableOpacity
onPress={() => {
handleAddTask();
}}>
<View style={{margin : 5}}>
<Text style={{fontSize: 24}}>+</Text>
</View>
</TouchableOpacity>
{taskItems.length ? taskItems.map(t=> <Text style={styles.paragraph}>{t}</Text>) : undefined}
</View>
);
Check on - snack.expo

Conditioning a button on React Native

I have a button that should be able to do an operation only if a previous validation is true, but to be honest I don't know how to do it; what I did is really messy so I belive there should be a correct way of doing this.
So this is what I've tried. I'm using hooks:
<View style={styles.buttonContainer2}>
<TouchableOpacity
style={ styles.logout}
onPress={
if( vValidCellphone == true{
() => onSubmit({
vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail,vCreationUser
})
})}>
<Text style={styles.loginText}>GUARDAR</Text>
</TouchableOpacity>
You can use touchable opacity props called disabled. Set it true to disable the onclick action as below :
<TouchableOpacity
style={ styles.logout}
disabled={!vValidCellphone}
onPress={() => onSubmit({
vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail,vCreationUser
})}>
<Text style={styles.loginText}>GUARDAR</Text
</TouchableOpacity>
In addition you can style your button according to disable condition to style button like disabled.

onTouch event not working

I am relatively new to React-Native.
I was trying to implement onTouch event but for some reason this doesn't seem to be working.
for example in this code
<View style={[container1,this.state.increased ? {backgroundColor: "#B4EEB4"} : null,this.state.decreased ? {backgroundColor: "#ffe5e5"} : null]} onPress={() => this.touched(this.props.key)}>
<View style={upperRow}>
<Text style={sno}> {this.props.no} </Text>
<Image
source={{uri: "https://coincap.io/images/coins/" + this.props.coinName + ".png"}}
style={img}
/>
<Text style={coinSymbol}>{this.props.coinShortName}</Text>
<Text style={coinPrice}>${this.props.coinPrice}</Text>
<View style={percentageBox}>
<Text style={this.props.percentChange < 0 ? percentChangeMinus : percentChangePlus }>{this.props.percentChange}%</Text>
</View>
</View>
<Display enable={stateToDisplay}>
<View style={statisticsContainer}>
<Text style={marketCap}>Cap: {this.props.marketCap}B </Text>
<Text style={seperator1}>|</Text>
<Text style={vwapData}>24vwap: {this.props.vwapData} </Text>
</View>
</Display>
</View>
Here
View style={[container1,this.state.increased ? {backgroundColor: "#B4EEB4"} : null,this.state.decreased ? {backgroundColor: "#ffe5e5"} : null]} onPress={() => this.touched(this.props.key)}>
I am passing this onPress event
onPress={() => this.touched(this.props.key)
which I expect should have called/run the function touched here
lass CoinCard extends Component {
state = {
increased: false,
decreased: false,
selectedPostId: "none"
}
componentWillReceiveProps(nextProps) {
if (this.props.coinPrice != nextProps.coinPrice ) {
if (this.props.coinPrice > nextProps.coinPrice) {
this.setState({decreased: true, increased: false})
}
if (this.props.coinPrice < nextProps.coinPrice) {
this.setState({increased: true, decreased: false})
}
}
}
touched = (id) => {
this.setState({selectedPostId: id})
console.log("inside touched")
}
[Question] But clicking on the container is doing nothing at the moment. Can anyone tell me what I am doing wrong here?
View component does not provide an onPress prop. You can either use TouchableHighlight or TouchableOpacity.
So while in React Native View does not have an onPress prop, it does have an onTouchStart, onTouchEnd events. This however will be called even if you touch the children inside the view, so its not a good way if you want the touch to be exclusively to the container outside the content in the view.
So you can either have onTouchStart and handle your onPress logic there, or wrap your entire view in a TouchableOpacity, TouchableHighlight or TouchableWithoutFeedback and handle the onPress on that.
More on React Native Touchables

Cannot display array in React Native

When i press the <TouchableOpacity> Button, i want the value 'abc' to be appended to the array selectedTags and then <Text> {this.list()} </Text> will print out my array.
But now when i press the Button, nothing display out.
Can anybody know what is the problem with my code?
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
selectedTags: []
}
}
list() {
return this.state.selectedTags.map(function(tags, i){
return(
<View key={i}>
<Text>{tags.name}</Text>
</View>
);
});
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={() => this.state.selectedTags.push('abc')} key = {1} style={styles.buttonContainer}>
<Text style={styles.buttonText}> Button </Text>
</TouchableOpacity>
<Text> {this.list()} </Text>
</View>
);
}
}
This is because you never call setState, which would trigger re-render of your component.
instead of using:
onPress={() => this.state.selectedTags.push('abc')}
try:
onPress={() => this.setState({selectedTags: this.state.selectedTags.concat('abc')})}
The function list only push data in array but does not rerender the view, todo so you have to use setState or forceUpdate.
You can implement the onpress function like this.
onPress = () =>{
this.state.selectedTags.push("abc");
this.setState({selectedTags : this.state.selectedTags});
}

React-native: Pass event to other object

This is my first experience with JS/React/React Native. I don't yet fully grasp mechanics of this framework, so be kind to me.
What I have :
<View style={styles.container}>
<View style={styles.timerContainer}>
<View style={styles.timerBar}>
<Image style={styles.icon} source={require('../../img/time50.png')}/>
{Timer} //First
</View>
<View style={styles.timerBar}>
<Image style={styles.icon} source={require('../../img/break50.png')}/>
{Timer} //Second
</View>
</View>
<View style={styles.buttonContainer}>
<TouchableHighlight onPress={this.startWork}>
<Image style={styles.imageButton} source={require('../../img/start.png')}/>
</TouchableHighlight>
<TouchableHighlight onPress={this.startBreak}>
<Image style={styles.imageButton} source={require('../../img/break.png')}/>
</TouchableHighlight>
<TouchableHighlight onPress={this.stopWork}>
<Image style={styles.imageButton} source={require('../../img/end.png')}/>
</TouchableHighlight>
</View>
</View>
Timer is a custom class, which will have 'start', 'pause' and 'end' methods. I want to call methods of both Timers when TouchableHighlight is pressed.
Overall it would look like this :
when first TouchableHighlight is pressed (startWork), Timer2.end and Timer1.start should be called, when second is pressed (startBreak), Timer1.pause, Timer2.start should be called, for third (stopWork) it would be Timer1.end, Timer2.end.
But how am I supposed to refer to these timers from onPress methods? Should I keep both Timers in some vars of parent class? I am totally stuck and have no idea where to start (and what's acceptable). Such problem is not easily googlable (or I don't know where to look). I would appreciate any help (solution, pointing to tutorial...).
When you render the timer components in this component you should assign a ref to each one of them, like
<Timer ref={r => this.timer1 = r}/>
Then in the Touchable callback functions you can call this.timer1.start()
Note: Cleaner ref setting would be to actually have another function, so you aren't constantly binding in the render function:
setTimerOne = (r) => {
this.timer1 = r;
}
render() {
<Timer ref={this.setTimerOne}/>
}

Categories

Resources