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.
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.
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.
Related
I have two very simple components and the pressables I have in my Start component just won't work, not the navigation or the console.log(), I can't even inspect them with the element inspector... I am using ImageBackground of react native for the first time so i don't know if this has something to do with it? Although, i did try removing it and i still couldn't press anything...
Here is my code for the Start component:
import React from 'react';
import {ImageBackground, Pressable, StyleSheet, Text, View} from 'react-native';
import { normalize } from '../../utils/helper';
import { colors } from '../../utils/styles';
const image = require('../../assets/images/start-page/start-page-background.png');
export default function Start({navigation}) {
const handleStartPress = () => {
console.log('hi');
navigation.navigate('Home');
};
return (
<View style={styles.container}>
<ImageBackground source={image} style={styles.image}>
<Pressable style={styles.startButton} onPress={() => handleStartPress()}>
<Text style={styles.startText}>Έναρξη</Text>
</Pressable>
<View style={styles.footer}>
<Pressable style={[styles.footerPressable, styles.conditions]}><Text style={styles.footerText}>blah</Text></Pressable>
<Text style={styles.code}>blah</Text>
<Pressable style={[styles.footerPressable, styles.policy]} onPress={() => console.log('policy')}><Text style={styles.footerText}>blah</Text></Pressable>
</View>
</ImageBackground>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
},
startButton: {
backgroundColor: colors.main.blue,
borderRadius: normalize(10),
paddingHorizontal: normalize(40),
paddingVertical: normalize(12),
alignSelf: 'center',
position: 'absolute',
bottom: normalize(180),
},
startText: {
color: 'white',
fontSize: normalize(30),
},
footer: {
paddingVertical: normalize(10),
position: 'absolute',
bottom: normalize(15),
},
conditions: {
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingLeft: normalize(10),
paddingRight: normalize(10),
},
policy: {
paddingLeft: normalize(10),
//zIndex: 999,
},
footerText: {
fontSize: normalize(16),
lineHeight: normalize(16),
color: 'black',
},
code: {
color: colors.main.blue,
fontWeight: '700',
fontSize: normalize(16),
lineHeight: normalize(16),
borderRightColor: 'black',
borderRightWidth: normalize(1),
paddingHorizontal: normalize(10),
},
});
I ran your code and it works fine. But I don't have any more information on your project (such as your RN version), so I can only make some educated guess.
The non-responsiveness can be caused by the other parts of your application that block your JS thread and prevent the event loop from passing message from the queue to the stack.
To debug this, you can toggle the perfMonitor to see if the JS thread frame rate has dropped to 0. You can also try not to render other elements (e.g. render solely this button in your App.tsx) in your app to see if the issue is gone.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
My add button gives me this error when I click it, but it still adds the input text to my firebase.
How do i get rid of this error?
import React, { Component } from 'react';
import { View, Text, StyleSheet, Button, TextInput, TouchableOpacity, ScrollView } from 'react-native';
import firebase from './firebase';
export default class App extends Component {
carDatabase = firebase.database().ref('car');
state = { cars: {}, selectedId: '', text: ''}
// Read
componentDidMount() {
this.carDatabase.on('value', cars => {
const carsJSON = cars.val();
this.setState({ cars: carsJSON === null ? {} : carsJSON });
})
// this.carDatabase.push({color: 'yellow'})
}
// Create
create() {
this.carDatabase.push('space') /// changes selected item
this.setState({selectedId: ''})
}
add() {
this.carDatabase.push(this.state.text).set(TextInput.value) /// pushes textput to firebase
this.setState(TextInput.value)
}
// Update
update() {
this.carDatabase.child(this.state.selectedId).set('space') /// changes text of selected item
this.setState({selectedId: ''})
}
// Delete
deleteCar() {
if(this.state.selectedId === '') { ///selects item
return;
}
this.carDatabase.child(this.state.selectedId).set(null) ///deletes item
this.setState({selectedId: ''})
}
render() {
return (
<View style={styles.container}>
<ScrollView>
<Text style={styles.top}>Todo List</Text>
<TextInput value={this.state.text} style={styles.textInput}></TextInput>
<Button title="create" onPress={() => this.create()}></Button>
<Button title="update" onPress={() => this.update()}></Button>
<Button title="delete" onPress={() => this.deleteCar()}></Button>
<Button title="add" onPress={() => this.add()}></Button>
{
Object.keys(this.state.cars).map( (carId, index, text) =>
<TouchableOpacity key={index} onPress={() => this.setState({ selectedId: carId, text})}>
<Text style={styles.input}>{`${JSON.stringify(this.state.cars[carId])}`} </Text>
</TouchableOpacity>
)
}
<TextInput ///creates text input
style={{height: 40}}
placeholder="Type here to add"
onChangeText={(text) => this.setState({text})}
value={this.state.text} ///gets text input
/>
<Text style={{padding: 10, fontSize: 42}}> {this.state.text.value} </Text>
</ScrollView>
{/* <Text>{JSON.stringify(this.state.cars, null, 2)}</Text> */}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
width: '100%'
},
textInput: {
backgroundColor: '#ADD8E6',
height: 40,
width: '100%'
},
input: {
backgroundColor: '#ADD8E6',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
top: {
backgroundColor: 'white',
height: 45,
paddingLeft: 140,
paddingTop: 20,
fontSize: 20,
alignItems: 'center',
justifyContent: 'center'
}
});
From the way you describe it, this is the call that is causing problems:
this.carDatabase.push(this.state.text).set(TextInput.value)
Since you say the database is still updated, it seems the push(...) works, but the set(...) is failing. As the error message says, that would be caused by TextInput.value being undefined.
If that is indeed the case, log the value of TextInput.value before you write it to the database and verify that it is what you expect it to be.
If the above is not the cause, then honesty it's too hard to determine exactly where the problem is coming from in what you've current shared. I'd recommend reducing the scope of your question and the code. Read how to create a minimal, complete, verifiable example to learn why and how to do that, is it will drastically increase the chances that someone may help and will also often reduce the downvotes that your question attracts.
I am quite new to React Native. I am familiar with React and use it for my work. React Native seems different in terms of applying styles to the components.
I am having issue applying styles to the button.
Here is my current code:
<Button
title="LET'S GET STARTED"
onPress={() => {
console.log('You tapped the Decrypt button!');
}}
buttonStyle={{
backgroundColor: "#0A6ABB",
width: 300,
height: 45,
borderColor: "#FFFFFF",
borderWidth: 2,
borderRadius: 5
}}
containerStyle={{ marginTop: 50 }}
/>
I tried multiple ways, but the styles are not being applied the button that I have created.
Here is the screenshot of how it looks like:
"Let's get started" is the button and no matter what it just has the default blue text.
How can I fix this?
Could anyone please help me with this?
Is your Button component imported from react-native? If yes then you can't style it because as stated on their documentation, below are the supported props, buttonStyle is not supported prop. Alternatively, maybe you can try other packages like Button from react-native-elements or NativeBase
onPress
title
accessibilityLabel
color
disabled
testID
hasTVPreferredFocus
Button is very limited in react native. You can use TouchableOpacity instead to give you more flexibility See documentation here.
TouchableOpacity example:
render () {
return (
<TouchableOpacity
style={styles.button}
onPress={this.onPress} >
<Text> LETS GET STARTED </Text>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: '#DDDDDD',
padding: 10
},
});
There are also different kinds of "buttons" depending on what you need like TouchableHighlight, TouchableWithoutFeedback
Use TouchableOpacity
import { StyleSheet, TouchableOpacity, Text }
render() {
return (
<TouchableOpacity
style={styles.button}
onPress={() => { console.log('You tapped the Decrypt button!'); }}
>
<Text> LET'S GET STARTED </Text>
</TouchableOpacity>
)
}
const styles = StyleSheet.create({
button: {
alignItems: 'center',
backgroundColor: "#0A6ABB",
width: 300,
height: 45,
borderColor: "#FFFFFF",
borderWidth: 2,
borderRadius: 5,
marginTop: 50
},
});
I'm trying to get a React Native app set up following this post and then ported over to ES6. Here's the main page code:
"use strict";
import React, { Component } from 'react';
import Camera from 'react-native-camera';
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
TouchableHighlight,
} from 'react-native';
export default class AwesomeProject extends Component {
constructor(props) {
super(props);
this.state = {cameraType: Camera.constants.Type.back};
}
render() {
return (
<Camera
ref="cam"
style={styles.container}
type={this.state.cameraType}>
<View style={styles.buttonBar}>
<TouchableHighlight style={styles.button} onPress={this._switchCamera.bind(this)}>
<Text style={styles.buttonText}>Flip</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.button} onPress={this._takePicture.bind(this)}>
<Text style={styles.buttonText}>Take</Text>
</TouchableHighlight>
</View>
</Camera>
);
}
_switchCamera: () => {
var state = this.state;
console.log(this.state);
state.cameraType = state.cameraType === Camera.constants.Type.back ? Camera.constants.Type.front : Camera.constants.Type.back;
this.setState(state);
}
_takePicture: () => {
console.log(this.refs);
this.refs.cam.capture(function(err, data) {
console.log(err, data);
});
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent",
},
buttonBar: {
flexDirection: "row",
position: "absolute",
bottom: 25,
right: 0,
left: 0,
justifyContent: "center"
},
button: {
padding: 10,
color: "#FFFFFF",
borderWidth: 1,
borderColor: "#FFFFFF",
margin: 5
},
buttonText: {
color: "#FFFFFF"
}
});
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
I am getting a weird error saying both state.cameraType is undefined and this.refs is undefined. I have a hunch that something is not getting bound and my this is not pointing to right thing but I have tried using both arrow functions and explicitly binding. See comment below. Anyway, I am not sure why it's acting up, any ideas?
Very similar to this post except I have tried both the proposed solutions so I feel like something else is missing or I'm doing the binding wrong.
edit: Is there reason to be downvoted? Am I not being clear on something :o
It turns out manual binding is the way to go, just needed to reload the app. I did not have hot-swapping enabled. Alternatively, arrow functions should also work.
Another thing to point out, for iOS 10 and above, you'll have to set 2 things in the Info.plist file, Privacy - Camera Usage Description and Privacy - Photo Library Usage. It can be any string value.
I hope all is well! First off, I'd like to thank you for being such a great developers and supporter of the SO community - you really make a difference!
I wanted to ask you about how to solve an error I continue to encounter when using react-native-overlay.
It seems when I put the overlay tags within a touchable highlight in order to bring the nested text to the forefront of the view - I get the following error:
Invariant Violation: Touchable child must either be native or forward setNativeProps to a native component. I have tried adding a native method within the class and that did not work (posted on another topic).
Any help would be greatly appreciated!
Here's my code so far:
/**
* Sample React Native App
* https://github.com/facebook/react-native
*/
'use strict';
var React = require('react-native');
var Overlay = require('react-native-overlay');
var {
Text,
View,
StyleSheet,
Image,
TouchableHighlight,
AppRegistry
} = React;
var styles = StyleSheet.create({
container: {
marginTop: 0,
flex: 1
},
buttonText: {
fontSize: 24,
color: 'white',
alignSelf: 'center',
},
bgImage: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'stretch',
resizeMode: 'cover',
},
});
class App extends React.Component{
makeBackground(btn){
var obj = {
flexDirection: 'row',
alignSelf: 'stretch',
justifyContent: 'center',
flex: 1,
backgroundColor: "#020202",
opacity: 0.3,
}
return obj;
}
goToProfile(){
console.log('Going to Profile');
}
goToRepos(){
console.log('Going to Repos');
}
goToNotes(){
console.log('Going to Notes');
}
render(){
return (
<View style={styles.container}>
<Image source={{uri: 'http://s3.amazonaws.com/rapgenius/1365796760_TommieSmithAP276.jpg'}} style={styles.bgImage} >
<TouchableHighlight
style={this.makeBackground(0)}
onPress={this.goToProfile.bind(this)}
underlayColor="#88D4F5">
<Overlay>
<Text style={styles.buttonText}>Causes</Text>
</Overlay>
</TouchableHighlight>
</Image>
<Image source={{uri: 'http://a57.foxnews.com/global.fncstatic.com/static/managed/assets/876/493/baltimore%20suspect%20injured.jpg?ve=1&tl=1'}} style={styles.bgImage}>
<TouchableHighlight
style={this.makeBackground(1)}
onPress={this.goToRepos.bind(this)}
underlayColor="#E39EBF">
<Text style={styles.buttonText}>News</Text>
</TouchableHighlight>
</Image>
<Image source={{uri: 'http://cdn.breitbart.com/mediaserver/Breitbart/Big-Government/2014/08/16/ferguson-rioter-tear-gas-AP.jpg'}} style={styles.bgImage}>
<TouchableHighlight
style={this.makeBackground(2)}
onPress={this.goToNotes.bind(this)}
underlayColor="#9BAAF3">
<Text style={styles.buttonText}>Hashtags</Text>
</TouchableHighlight>
</Image>
<Image source={{uri: 'http://www.swurvradio.com/wp-content/uploads/2015/06/Jason-Derulo-Ciara-and-Tinashe-honor-Janet-Jackson-with-a-dance-medley-at-the-BET-Awards-on-June-28-2015-in-Los-Angeles..jpg'}} style={styles.bgImage}>
<TouchableHighlight
style={this.makeBackground(3)}
onPress={this.goToNotes.bind(this)}
underlayColor="#9BAAF3">
<Text style={styles.buttonText}>Entertainment</Text>
</TouchableHighlight>
</Image>
</View>
)
}
};
AppRegistry.registerComponent('App', () => App);
The error I get is the following:
Error: Invariant Violation: Touchable child must either be native or forward setNativeProps to a native component
stack:
ensureComponentIsNative index.ios.bundle:35696
React.createClass.componentDidMount index.ios.bundle:35353
CallbackQueue.assign.notifyAll index.ios.bundle:5332
ReactNativeReconcileTransaction.ON_DOM_READY_QUEUEING.close index.ios.bundle:16113
ReactNativeReconcileTransaction.Mixin.closeAll index.ios.bundle:6636
ReactNativeReconcileTransaction.Mixin.perform index.ios.bundle:6577
batchedMountComponentIntoNode index.ios.bundle:8012
Object.ReactDefaultBatchingStrategy.batchedUpdates index.ios.bundle:15893
Object.batchedUpdates index.ios.bundle:5095
URL: undefined
line: undefined
message: Invariant Violation: Touchable child must either be native or forward setNativeProps to a native componenthandleException # ExceptionsManager.js:62
All Touchable has only one child and it should be native (View, Text, Image etc).