Error: "Invalid data message - all must be length: 8" - PickerIOS - ios

Edit: it seems that if I comment out the line "this.setState({logged_in: true});", line 63, that I don't get the error. My guess is that something about the way I'm trying to change the content being displayed in the render function based on if the user is logged in or not is what is the cause of this error. Any ideas?
I've been making some slight progress in understanding some very basics of React Native, I feel like. Although my code might not be pretty, up until some recent additions it worked. I'm recieving an error message in the IOS Simulator that reads "Invalid data message - all must be length: 8". It unfortunately isn't giving me any specifics that I understand, such as linenumbers.
I sincerely apologise if this is a repost, I've been looking like crazy on google and stackoverflow to find a solution to this error but have been unsuccessful in my searches.
I've censored the url I've using in fetch since it is an adress for testing within the company in very early stages, but I am 99,99% sure that's not where the problem lies.
My index.ios.js:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Button,
Alert,
TextInput,
TouchableHighlight,
Image,
AlertIOS,
PickerIOS,
} from 'react-native';
var REASONS = {
sick: {
name: "sjuk"
},
vacation: {
name: "semester"
},
child_care: {
name: "vård av barn"
},
parenting: {
name: "föräldraledig"
},
general: {
name: "övrigt"
},
};
export default class mbab_franvaro extends Component {
constructor(props) {
super(props);
this.state = {username: '', password: '', logged_in: false, reason: 'sjuk'};
}
logout(){
this.setState({logged_in: false});
this.username = ""; this.password = "";
}
login(){
if(this.state.username == "" || this.state.password == ""){
AlertIOS.alert("Fel", "Vänligen fyll i alla fält.");
}
else{
fetch("MY_PRIVATAE_COMPANY_URL", {
method: "POST",
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Content-Type': 'application/x-www-form-urlencoded',
},
body: "username=" + this.state.username + "&password=" + this.state.password,
})
.then((response) => response.json())
.then((response) => {
if(JSON.stringify(response.body).replace(new RegExp('"', 'g'), '').match("Inloggad")){
this.username = this.state.username; this.password = this.state.password;
this.setState({logged_in: true});
//AlertIOS.alert("Hej!", "Välkommen " + this.username + "!");
}
else{
AlertIOS.alert(
"Fel",
JSON.stringify(response.body).replace(new RegExp('"', 'g'), '')
);
}
})
.catch((error) => {
AlertIOS.alert("error", error);
})
.done();
}
}
render(){
if(this.state.logged_in){
//sidan för frånvarorapportering
return (
<View style={styles.container}>
/*<TouchableHighlight style={styles.logout_button} onPress={() => this.logout()}>
<Text style={styles.login_button_text}>Logga ut</Text>
</TouchableHighlight>*/
<View style={styles.report_wrapper}>
<Text style={styles.header}>Frånvarorapportering</Text>
<Text>Ange anledning och hur stor del av dagen du blir frånvarande.</Text>
<PickerIOS
selectedValue={this.state.reason}
onValueChange={(reason) => this.setState({reason})}>
{Object.keys(REASONS).map((reason) => (
<PickerItemIOS
key={reason}
value={reason}
label={REASONS[reason].name}
/>
))}
</PickerIOS>
</View>
</View>
);
}
else{
//inloggningssidan
return (
<View style={styles.container}>
<Image resizeMode="center" style={styles.logo} source={require('./app/res/logo_cmyk.png')} />
<TextInput
placeholder="Namn"
autocorrect={false}
style={styles.text_box}
onChangeText={(username) => this.setState({username})}
/>
<TextInput
placeholder="Lösenord"
autocorrect={false}
secureTextEntry={true}
style={styles.text_box}
onChangeText={(password) => {this.setState({password})}}
/>
<TouchableHighlight style={styles.login_button} onPress={() => this.login()}>
<Text style={styles.login_button_text}>Logga in</Text>
</TouchableHighlight>
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F4F4F4',
},
report_wrapper: {
flex: 1,
},
logout_button: {
flex: 0,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginLeft: 10,
marginRight: 10,
marginTop: 30,
marginBottom: 2,
padding: 10,
backgroundColor: "#003878"
},
login_button: {
flex: 0,
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
marginLeft: 10,
marginRight: 10,
marginTop: 2,
marginBottom: 2,
padding: 10,
backgroundColor: "#003878"
},
login_button_text: {
color: "white",
fontSize: 20,
flex: 1,
textAlign: "center",
},
logo: {
//flex: 1,
},
text_box: {
height: 40,
flex: 0,
backgroundColor: "white",
marginLeft: 10,
marginRight: 10,
marginTop: 2,
marginBottom: 2,
padding: 10
},
header: {
color: "#84754E",
fontSize: 25,
marginTop: 30,
},
});
AppRegistry.registerComponent('mbab_franvaro', () => mbab_franvaro);
Edit:

Add toString() to error did the trick for me:
.catch((error) => {
AlertIOS.alert("error", error.toString());
})

I was also getting the same error while using ScrollView.
Took me 2 days to figure out the solution.
I wasn't importing ScrollView from react-native.
Check if you've imported the Picker or not. :)

Related

How to stop echo in iOS side react native audio-record-player?

Below my code for playing voice clip I send here from previous screen
import * as Progress from 'react-native-progress';
import { FontFamily, Fonts } from '../../common/GConstants';
import { Image, SafeAreaView, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import React, { Component } from 'react';
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import AudioRecorderPlayer from 'react-native-audio-recorder-player';
import Colors from '../../common/GColors';
import GColors from '../../common/GColors';
import KeepAwake from 'react-native-keep-awake';
import WaveForm from 'react-native-audiowaveform';
import images from '../../assets/images/index';
import { secondsToTime } from '../../common/GFunction';
export default class ConfirmRecording extends Component {
constructor() {
super();
this.state = {
recordTime: '',
duration: '',
isPlaying: false,
totalDuration: '',
audioPath: '',
currentPositionSec: '',
currentDurationSec: '',
};
this.audioRecorderPlayer = new AudioRecorderPlayer();
}
showProgress = () => {
if (this.state.currentPositionSec / this.state.totalDuration > 1) {
return Math.round(
this.state.currentPositionSec / this.state.totalDuration,
);
} else {
return Math.fround(
this.state.currentPositionSec / this.state.totalDuration,
);
}
};
onStartPlay = async () => {
console.log('START and is playing', this.state.audioPath + "--------" + this.state.isPlaying);
if (this.state.isPlaying) {
this.setState({ isPlaying: false });
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
} else {
const msg = await this.audioRecorderPlayer.startPlayer(
this.state.audioPath,
// 'http://podcasts.cnn.net/cnn/services/podcasting/specials/audio/2007/05/milesobrien.mp3',
);
console.log('Play MSG', msg);
this.audioRecorderPlayer.addPlayBackListener((e) => {
this.setState({
isPlaying: true,
currentPositionSec: Math.round(
Math.round(Math.round(e.current_position / 10) / 100),
),
currentDurationSec: Math.round(Math.round(e.duration / 10) / 100),
playTime: e.current_position,
duration: e.duration,
});
if (e.duration == e.current_position) {
this.setState({ isPlaying: false });
console.log('Stopped');
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
}
return;
});
}
};
componentDidMount = () => {
var audioPath = this.props.navigation.getParam('audioPath');
var duration = this.props.navigation.getParam('duration');
console.warn("Data from prevciouyas screen", audioPath + "--------" + duration)
this.setState({
audioPath: audioPath,
duration: duration
});
}
componentWillUnmount = () => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({
audioPath: '',
isPlaying: false
});
}
render() {
return (
<SafeAreaView style={style.mainContainer}>
<View style={style.audioView}>
<Text style={style.audioViewText}>Confirm Recording</Text>
<View style={{ marginTop: hp(2) }}>
<View style={style.secondWaveView}>
<WaveForm
style={style.WaveForm}
source={{ uri: this.state.audioPath }} // not work
stop={this.state.isPlaying}
play={this.state.isPlaying}
// autoPlay={true}
waveFormStyle={{ waveColor: Colors.gray, scrubColor: Colors.darkBlue }}
/>
<Text> {secondsToTime(this.state.currentPositionSec)
.m.toString()
.padStart(2, 0) +
':' +
secondsToTime(this.state.currentPositionSec)
.s.toString()
.padStart(2, 0)}</Text>
</View>
<View style={style.secondAudioView}>
<TouchableOpacity
onPress={(event) => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({ audioPath: '', isPlaying: false }, () => {
// add Imerssion
// this.props.navigation.state.params.a(true),
this.props.navigation.navigate('ImpressionPro')
});
}
}
activeOpacity={.9}>
<Image source={images.sendIcon} />
</TouchableOpacity>
<View style={{ flex: 1 }} />
<TouchableOpacity style={style.icon}
onPress={() => {
this.audioRecorderPlayer.stopPlayer();
this.audioRecorderPlayer.removePlayBackListener();
this.setState({ audioPath: '', isPlaying: false }, () => {
this.props.navigation.pop(2)
});
}}
activeOpacity={.9}>
<Image source={images.deleteCancelBtn} />
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.onStartPlay()
.then(() => {
console.log('Playing');
})
.catch((err) => {
console.log('PErr', err);
});
}}
style={style.icon} activeOpacity={.9}>
<Image source={images.playBtn} />
</TouchableOpacity>
</View>
</View>
</View>
<KeepAwake />
</SafeAreaView>
)
}
}
const style = StyleSheet.create({
mainContainer:
{
flex: 1,
backgroundColor: Colors.darkBlue,
justifyContent: 'center',
alignItems: 'center'
},
secondWaveView:
{
marginTop: hp(2),
marginHorizontal: wp(5.5),
flexDirection: 'row',
justifyContent: 'space-between',
},
secondAudioView:
{
flexDirection: 'row',
marginTop: hp(2),
marginStart: wp(5)
},
WaveForm:
{
height: 25,
flex: 1,
},
icon:
{
marginEnd: wp(5)
},
audioView:
{
backgroundColor: Colors.white,
height: "25%",
width: "88%",
alignSelf: 'center',
borderRadius: hp(2),
},
audioViewText:
{
textAlign: 'center',
marginTop: hp(2),
fontSize: Fonts.fontsize20,
marginHorizontal: wp(6),
fontFamily: FontFamily.medium,
color: Colors.textCoffeeColor
},
})
issue was in the waveform for echo ... both were playing same time so thats why issue generated...

react-native-gesture-handler not working on ios

I have yarn installed react-native-gesture-handler,I then cd'd into ios and pod installed. I then reran the react-native run-ios and still when I swipe nothing happens whatsoever. Im getting zero errors it just doesn't swipe whatsoever. Am i doing something wrong? I have tried to remedy this situation anyway possible and It just doesn't seem to swipe no matter what.
my code is as follows:
import React, {useState} from 'react';
import {
Platform,
View,
Text,
StyleSheet,
Image,
TouchableOpacity,
flatList,
} from 'react-native';
import Swipeable from 'react-native-gesture-handler/Swipeable';
const styles = StyleSheet.create({
container: {
padding: 20,
flexDirection: 'row',
backgroundColor: '#fff',
justifyContent: 'space-between',
alignItems: 'center',
},
text: {
fontSize: 18,
color: '#69696969',
},
icon: {
height: 30,
tintColor: '#69696969',
...Platform.select({
ios: {
tintColor: 'blue',
},
android: {
tintColor: 'red',
},
}),
},
separator: {
flex: 1,
height: 1,
backgroundColor: 'rgba(0, 0, 0, 0.2)',
},
});
export const Separator = () => <View style={styles.separator} />;
const LeftAction = () => {
<View>
<Text>test</Text>
</View>;
};
const ListItem = ({name, onFavoritePress}) => {
const [isFavorite, setIsFavorite] = useState(false);
let starIcon;
if (isFavorite) {
starIcon = Platform.select({
ios: require('../assets/icons/ios-star.png'),
android: require('../assets/icons/md-star.png'),
});
} else {
starIcon = Platform.select({
ios: require('../assets/icons/ios-star-outline.png'),
android: require('../assets/icons/md-star-outline.png'),
});
}
return (
<Swipeable renderLeftActions={LeftAction}>
<View style={styles.container}>
<Text style={styles.text}>{name}</Text>
{onFavoritePress && (
<TouchableOpacity
onPress={() => setIsFavorite((prevIsFavorite) => !prevIsFavorite)}>
<Image style={styles.icon} resizeMode="contain" source={starIcon} />
</TouchableOpacity>
)}
</View>
</Swipeable>
);
};
export default ListItem;
You need to link RNGH to RN
run react-native link react-native-gesture-handler
if this doesn't work maybe you don't have cocoapads dependencies
to install it
run cd <your-ios-code-directory> && pod install

Function generating data according to state value not changing after first render

I am creating a Login and Register screen and I want the use to have an option to choose to register with email or phone number.
I am using a radio button for this, and for some reason the function does not change its render when I change the state(the state is for sure changed, I checked it with console.log).
Code:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
//login
email: "",
password: "",
//register
firstName: "",
lastName: "",
date: new Date(),
checked: "Use Email Address",
...
}
}
componentDidMount() {
...
Register = Register.bind(this);
RadioButton = RadioButton.bind(this);
}
onRadioChange(label) {
if (label === "Use Email Address") {
this.setState({ checked: "Use Email Address"})
console.log('test2')
} else {
this.setState({ checked: "Use Phone Number" })
console.log('test')
console.log(this.state.checked)
}
}
render() {
return (
<Stack.Navigator initialRouteName="Login">
<Stack.Screen name="Login" component={Login} options={{ headerShown: false }} />
<Stack.Screen name="Register" component={Register} options={{ headerShown: false }} />
</Stack.Navigator>
)
}
}
function RadioButton(label) {
return (
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 5, marginBottom: 5 }}>
<TouchableOpacity
onPress={() => { this.onRadioChange(label) }}
style={{
height: 24,
width: 24,
borderRadius: 12,
borderWidth: 2,
borderColor: '#FF9C09',
alignItems: 'center',
justifyContent: 'center',
}}>
{
this.state.checked === label ?
<View style={{
height: 10,
width: 10,
borderRadius: 5,
backgroundColor: '#FF9C09',
}} />
: null
}
</TouchableOpacity>
<Text style={{ marginLeft: 10, fontFamily: 'open-sans-regular' }}>{label}</Text>
</View>
);
}
function Register({navigation}) {
...
return(
...
{RadioButton("Use Email Address")}
{RadioButton("Use Phone Number")}
...
)
}
I guess this has something to do with the lifecycles? I mean I am updating the state and I binded this with function RadioButton.
Note: When it's first loaded it shows "Use Email Address" as checked correctly. It just does not change when I check "Use Phone Number".
Any help would be very much appreciated.

react-native: image won't rerender when state changes

I have an icon as an image and I want to change the icon when a state property changes. Here is the relevant code:
<TouchableHighlight underlayColor="rgba(0,0,0,0)" style={styles.playButton} onPress={this._handleStartPress}>
<Image source={(this.state.started) ? require('./Control-pause.png') : require('./Control-play.png')} resizeMode="contain" style={styles.icon}/>
</TouchableHighlight>
The state changes correctly as expected (verifed by some console logs), but somehow the Image won't re render and change when this.state.started changes. The path to the images is also correct.
Any Ideas what's the problem?
EDIT: The whole component:
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
TouchableHighlight,
View,
ScrollView,
Vibration,
AlertIOS,
Image
} from 'react-native'
/*import Icon from 'react-native-vector-icons/FontAwesome';*/
const timer = require('react-native-timer');
const Button = require('./components/Button.js');
const PlayIcon = require('./Control-play.png');
const PauseIcon = require('./Control-pause.png');
class Project extends Component {
constructor(props) {
super(props);
this.state = {
timerValue: 25*60,
count: 0,
started: false,
};
this._tick = this._tick.bind(this);
this._runClock = this._runClock.bind(this);
this._stopClock = this._stopClock.bind(this);
this._handlePomodoroPress = this._handlePomodoroPress.bind(this);
this._handlePausePress = this._handlePausePress.bind(this);
this._getMinsSecs = this._getMinsSecs.bind(this);
this._finishedTimer = this._finishedTimer.bind(this);
this._handleStartPress = this._handleStartPress.bind(this);
}
_tick() {
if (this.state.timerValue > 0) {
this.setState({timerValue: this.state.timerValue - 1});
} else {
this._finishedTimer();
}
}
_finishedTimer() {
this.setState({started: false});
timer.clearInterval('timer');
Vibration.vibrate();
AlertIOS.alert("Time's up!");
}
_runClock() {
this.setState({started: true});
console.log("running: ", this.state.started);
timer.setInterval('timer', this._tick, 1000);
}
_stopClock() {
this.setState({started: false});
console.log("running: ", this.state.started);
timer.clearInterval('timer');
}
_getMinsSecs(seconds) {
let mins = Math.floor(seconds / 60);
let secs = seconds - mins * 60;
return (mins < 10 ? "0" : "") + mins + ":" + (secs <10 ? "0" : "") + secs;
}
_handleStartPress() {
if (!this.state.started) {
this._runClock();
} else {
this._stopClock();
}
}
_handlePomodoroPress() {
if (!this.state.started) {
this.setState({timerValue: 25*60});
}
}
_handlePausePress() {
if(!this.state.started) {
this.setState({ timerValue: 5*60 });
}
}
render() {
return (
<View style={styles.container}>
<View style={styles.timeWrapper}>
<View style={styles.line}/>
<Text style={styles.time}>{this._getMinsSecs(this.state.timerValue)}</Text>
<View style={styles.line}/>
</View>
<TouchableHighlight underlayColor="rgba(0,0,0,0)" style={styles.playButton} onPress={this._handleStartPress}>
<Image source={(this.state.started) ? require('./Control-pause.png') : require('./Control-play.png')} resizeMode="contain" style={styles.icon}/>
</TouchableHighlight>
<View style={styles.buttonWrapper}>
<Button
value="Pomodoro"
onPress={this._handlePomodoroPress}/>
<Button value="Pause" onPress={this._handlePausePress}/>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "space-around",
alignItems: 'center',
backgroundColor: "#7CCF9E"
},
time: {
fontSize: 74,
color: '#fff',
fontWeight: '200'
},
buttonWrapper: {
justifyContent: 'center',
alignItems: 'center'
},
playButton: {
width: 79,
height: 79,
borderRadius: 100,
borderWidth: 3,
borderColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
line: {
marginTop: 10,
height: 3,
width: 200,
backgroundColor: '#fff'
},
timeWrapper: {
alignItems: 'center'
},
icon: {
height: 42,
}
});
AppRegistry.registerComponent('Project', () => Project);
something like this works easily:
<TouchableHighlight underlayColor="rgba(0,0,0,0)" style={styles.playButton} onPress={this._handleStartPress}>
<Text>{this.state.started ? "started" : "stopped"}</Text>
</TouchableHighlight>
EDIT2:
I found what causes the picture not to rerender!!!!
When I style the size in the StyleSheet it won't rerender ... If it has no size style everything is fine!
require calls are not dynamic. They are statically analyzed and bundled. https://github.com/facebook/react-native/issues/2481 . As Andrew Axton suggested, load them in separate variables outside of render and using that in the conditional should work.

left side of screen untouchable when using NavigatorIOS react-native

I have this very strange bug on my react-native iOS app, when I'm using NavigatorIOS (need it) : there is a 30 points zone on the left of the screen that is not touchable on the first touch (nothing happens on touchableHighlight or TouchableWithoutFeedback) in Listview elements for example...
When I use Navigator, no problem at all, it's specific to NavigatorIOS (and I need it in this part of the app), also tried without any style, same problem.
Haven't seen any github issue or discussion about this bug.
Edit :
Runnable example : https://rnplay.org/apps/E0R2vg
Component code sample:
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
NavigatorIOS,
ListView,
TouchableWithoutFeedback,
Dimensions,
} = React;
var myListView = React.createClass({
getInitialState: function() {
return {
ds: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
};
},
componentDidMount: function() {
console.log('feed datasource');
this.setState({
ds: this.state.ds.cloneWithRows([{name: 'one'}, {name:'two'}, {name: 'three'}]),
});
},
render: function() {
return (
<View style={styles.container}>
<ListView
dataSource={this.state.ds}
renderRow={this.renderItem}
style={styles.listView}
/>
<TouchableWithoutFeedback onPress={this.nextroute}>
<View style={[styles.pressme, {flex:1}]}>
<Text>Next route to see the issue</Text>
</View>
</TouchableWithoutFeedback>
</View>
);
},
renderItem: function(item) {
return (
<View style={styles.row}>
<TouchableWithoutFeedback onPress={() => alert('pressed')}>
<View style={styles.pressme}>
<Text>x</Text>
</View>
</TouchableWithoutFeedback>
<Text>{item.name} - Item description...</Text>
</View>
);
},
nextroute: function() {
this.props.navigator.push({
title: 'Try press [x] (twice)',
component: myListView,
onLeftButtonPress: () => this.props.navigator.pop(),
});
},
});
var SampleApp = React.createClass({
render: function() {
return (
<NavigatorIOS
style={styles.navcontainer}
initialRoute={{
component: myListView,
title: 'First view is ok',
}}
tintColor="#000000"
barTintColor="#fd7672"
translucent={false}
ref='navios'
/>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 28,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
fontSize: 19,
marginBottom: 5,
},
navcontainer: {
flex: 1,
},
listView: {
flex: 1,
width: Dimensions.get('window').width,
},
row: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#FFFFFF',
},
pressme: {
margin: 10,
borderWidth: 1,
borderColor: 'red',
padding: 15,
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);

Resources