215

I'm making an android app using react native and I've used TouchableOpacity component to create buttons.
I use a text input component to accept text from the user and the button should only be enabled once the text input matches a certain string.
I can think of a way to do this by initially rendering the button without the TouchableOpactiy wrapper and re-rendering with the wrapper once the input string matches.
But I'm guessing there is a much better way to do this. Can anyone help?

15 Answers 15

433

TouchableOpacity extends TouchableWithoutFeedback, so you can just use the disabled property :

<TouchableOpacity disabled={true}>
  <Text>I'm disabled</Text>
</TouchableOpacity>

React Native TouchableWithoutFeedback #disabled documentation

The new Pressable API has a disabled option too :

<Pressable disabled={true}>
  {({ pressed }) => (
    <Text>I'm disabled</Text>
  )}
</Pressable>
3
  • Well do you have anything that might give an hint on what it's not working for you ? What version of RN do you use ? Can you show us some code ? Just a link to the RN documentation to help you: facebook.github.io/react-native/docs/… Commented Jun 5, 2017 at 7:03
  • 21
    Notice the disabled state doesn't change child rendering styles so in order to make the disabled state visible to users you would need to apply a style to the Text element such as <Text style={{ opacity: 0.5 }}>I'm disabled</Text> -- just a FYI Commented Oct 16, 2017 at 12:25
  • 1
    In addition to what Peter has suggested here, you can also change the opacity level for the button when the touch is active (defaults to 0.2 for now). reactnative.dev/docs/touchableopacity#activeopacity
    – N3R4ZZuRR0
    Commented Mar 14, 2021 at 6:12
60

Just do this

<TouchableOpacity activeOpacity={disabled ? 1 : 0.7} onPress={!disabled && onPress}>
  <View>
    <Text>{text}</Text>
  </View>
</TouchableOpacity>
3
  • <Text>{text}</FontText>? FontText?
    – jcollum
    Commented Apr 3, 2017 at 19:20
  • 17
    onPress is not expecting a boolean Commented Nov 22, 2017 at 13:22
  • second press gives this error. TypeError: onPress is not a function. (In 'onPress(event)', 'onPress' is false) Solution not recommended.
    – Arosha
    Commented Dec 30, 2020 at 2:46
7

this native-base there is solution:

<Button
    block
    disabled={!learnedWordsByUser.length}
    style={{ marginTop: 10 }}
    onPress={learnedWordsByUser.length && () => {
      onFlipCardsGenerateNewWords(learnedWordsByUser)
      onFlipCardsBtnPress()
    }}
>
    <Text>Let's Review</Text>
</Button>
5

So it is very easy to disable any button in react native

<TouchableOpacity disabled={true}>
    <Text> 
          This is disabled button
   </Text>
</TouchableOpacity>

disabled is a prop in react native and when you set its value to "true" it will disable your button

Happy Cooding

4

This seems like the kind of thing that could be solved using a Higher Order Component. I could be wrong though because I'm struggling to understand it 100% myself, but maybe it'll be helpful to you (here's a couple links)...

3

TouchableOpacity receives activeOpacity. You can do something like this

<TouchableOpacity activeOpacity={enabled ? 0.5 : 1}>
</TouchableOpacity>

So if it's enabled, it will look normal, otherwise, it will look just like touchablewithoutfeedback.

2
  • 2
    But that still doesn't disable it. Just doesn't change opacity on touch. Commented Nov 1, 2015 at 8:02
  • 1
    You could do something like onPress={@someMethod if enabled}. In this way, you won't have to wrap your view in different views or touchables. Commented Nov 1, 2015 at 11:38
2

To disable Text you have to set the opacity:0 in Text style like this:

<TouchableOpacity style={{opacity:0}}>
  <Text>I'm disabled</Text>
</TouchableOpacity>
2

You can use the disabled prop in TouchableOpacity when your input does not match the string

<TouchableOpacity disabled = { stringMatched ? false : true }>
    <Text>Some Text</Text>
</TouchableOpacity>

where stringMatched is a state.

1

You can build an CustButton with TouchableWithoutFeedback, and set the effect and logic you want with onPressIn, onPressout or other props.

1

I was able to fix this by putting a conditional in the style property.

const startQuizDisabled = () => props.deck.cards.length === 0;

<TouchableOpacity
  style={startQuizDisabled() ? styles.androidStartQuizDisable : styles.androidStartQuiz}
  onPress={startQuiz}
  disabled={startQuizDisabled()}
>
  <Text 
    style={styles.androidStartQuizBtn} 
  >Start Quiz</Text>
</TouchableOpacity>

const styles = StyleSheet.create({
androidStartQuiz: {
    marginTop:25,
    backgroundColor: "green",
    padding: 10,
    borderRadius: 5,
    borderWidth: 1
},
androidStartQuizDisable: {
    marginTop:25,
    backgroundColor: "green",
    padding: 10,
    borderRadius: 5,
    borderWidth: 1,
    opacity: 0.4
},
androidStartQuizBtn: {
    color: "white",
    fontSize: 24
}
})
1

I think the most efficient way is to wrap the touchableOpacity with a view and add the prop pointerEvents with a style condition.

<View style={this.state.disabled && commonStyles.buttonDisabled}        
      pointerEvents={this.state.disabled ? "none" : "auto"}>
  <TouchableOpacity
    style={styles.connectButton}>
  <Text style={styles.connectButtonText}">CONNECT </Text>
  </TouchableOpacity>
</View>

CSS:

buttonDisabled: {
    opacity: 0.7
  }
0

Here's my work around for this I hope it helps :

<TouchableOpacity
    onPress={() => {
        this.onSubmit()
    }}
    disabled={this.state.validity}
    style={this.state.validity ?
          SignUpStyleSheet.inputStyle :
          [SignUpStyleSheet.inputAndButton, {opacity: 0.5}]}>
    <Text style={SignUpStyleSheet.buttonsText}>Sign-Up</Text>
</TouchableOpacity>

in SignUpStyleSheet.inputStyle holds the style for the button when it disabled or not, then in style={this.state.validity ? SignUpStyleSheet.inputStyle : [SignUpStyleSheet.inputAndButton, {opacity: 0.5}]} I add the opacity property if the button is disabled.

0

You can enable and disable button or by using condition or directly by default it will be disable : true

 // in calling function of button 
    handledisableenable()
        {
         // set the state for disabling or enabling the button
           if(ifSomeConditionReturnsTrue)
            {
                this.setState({ Isbuttonenable : true })
            }
          else
          {
             this.setState({ Isbuttonenable : false})
          }
        }

<TouchableOpacity onPress ={this.handledisableenable} disabled= 
     {this.state.Isbuttonenable}>

    <Text> Button </Text>
</TouchableOpacity>
0

Use disabled true property

<TouchableOpacity disabled={true}> </TouchableOpacity>
0

Here is the simplest solution ever:

You can add onPressOut event to the TouchableOpcaity and do whatever you want to do. It will not let user to press again until onPressOut is done

1
  • 1
    Welcome to SO. Though we thank you for your answer, it would be better if it provided additional value on top of the other answers. In this case, your answer does not provide additional value, since Fomahaut already mentioned that solution. If a previous answer was helpful to you, you should vote it up once you have enough reputation.
    – Doj
    Commented Jan 4, 2021 at 6:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.