0xPingo
0xPingo

Reputation: 2197

React Native - TouchableOpacity causing app to crash on Android

I have a simple component that toggles between two sets of items - Hours & Happy Hours. The component works fine on iOS, but causes my app to crash (silently) on Android.

I have a working example here: https://snack.expo.io/Sk92sIEmf. And here is the code used, for reference:

import React, { Component } from 'react';
import { Dimensions, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

const { width } = Dimensions.get('window');

export default class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      showAnother: true,
      oneThingActive: false,
      anotherActive: true,
    };
  }

  handlePress = () => {
    const { anotherActive, oneThingActive } = this.state
    return this.setState({ anotherActive: !anotherActive, oneThingActive: !oneThingActive });
  }

  render() {

    const { showAnother, oneThingActive, anotherActive  } = this.state

    return (
      <View style={s.container}>
        <View style={s.sRow}>
          <TouchableOpacity style={s.titleCont} activeOpacity='1' onPress={this.handlePress}>
            <Text style={[s.text, s.title, !oneThingActive && s.inactive]}>ONE THING</Text>
          </TouchableOpacity>
          { showAnother &&
            <Text style={[s.text, s.title]}>|</Text>
          }
          { showAnother &&
            <TouchableOpacity style={s.titleCont} activeOpacity='1' onPress={this.handlePress}>
              <Text style={[s.text, s.title, !anotherActive && s.inactive]}>ANOTHER</Text>
            </TouchableOpacity>
          }
        </View>
        { oneThingActive &&
          <View style={s.row}>
            <Text style={[s.text, s.day]}>testing..</Text>
          </View>
        }
        { anotherActive &&
          <View style={s.row}>
            <Text style={[s.text, s.day]}>123..</Text>
          </View>
        }
      </View>
    )
  }
}

const s = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    marginHorizontal: 35,
    marginVertical: 5,
    borderColor: '#D4D4D4',
    borderTopWidth: 1,
    borderBottomWidth: 1,
  },
  titleCont: {
    alignSelf: 'flex-start',
  },
  title: {
    color: '#232323',
    fontSize: 14,
    alignSelf: 'flex-start',
    marginHorizontal: 5,
  },
  text: {
    color: '#232323',
    fontSize: 13,
  },
  inactive: {
    color: '#95989A',
  },
  row: {
    display: 'flex',
    flexDirection: 'row',
  },
  sRow: {
    display: 'flex',
    flexDirection: 'row',
    width: width,
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 5,
  },
})

As stated earlier, I don't really get an error when this crashes. At one point, I saw something to the effect of "attempted to assign read only property," but I am no longer seeing that error message. Any help or a point in the right direction would be greatly appreciated.

Thanks !

Edit:

Updated with a simplified example. It seems the crash is coming from the conditional render (this.state.oneThingActive && ...), a pattern I frequently use and have not run into any issues like this with.

The best way to reproduce is to visit this link: https://snack.expo.io/Sk92sIEmf, which has an IDE setup for React Native apps. You should find that the toggle works fine when the Platform is iOS, but once a state change is attempted in the Android version the app crashes.

Edit 2:

Seems the problem was due to the usage of TouchableOpacity.... I noticed the Android app was crashing from a console.log("..."), so I tried swapping in TouchableHighlight and got it to work. Going to investigate this more over the coming days, but would love to hear input if anyone has some.

Answer

This all seems a bit silly now, but my error was getting caused by activeOpacity='1'. I was passing in 1 as a String instead of as a Number. activeOpacity={1}does the trick. Do yourself a favor (unlike me in this instance) and use a linter.

Upvotes: 1

Views: 3354

Answers (2)

kojow7
kojow7

Reputation: 11384

I just encountered the same thing. In my case it was an issue of it not liking quotes in my style. Not sure about your case, but in my case when I added a

style={{marginRight: "20px"}}

by mistake it crashed. I should have had

style={{marginRight: 20}}

instead. Even just having

style={{marginRight: '20'}}

or

{{marginRight: "20"}}

causes it to crash.

I notice that you have activeOpacity='1' in your code and am wondering if you remove the quotes around the 1 whether it solve your problem.

Upvotes: 4

A. Goodale
A. Goodale

Reputation: 1348

This looks like a problem with the fact that class methods are not automatically bound to the instance. Add these to your constructor:

this.hoursPressed = this.hoursPressed.bind(this);
this.happyHoursPressed = this.happyHoursPressed.bind(this);

This is a common problem with using ES6 classes with React.

Upvotes: -1

Related Questions