Autocomplete with react native - reactjs

can someone please help me debug this code, I'd like to use 'react-native-autocomplete-input' library to autocomplete a search text input, basically the api request return a list of stock symbols and company names and I'm thinking to store this file locally to make it faster, for right now I just want to make it work using fetch. The autocomplete must search in responseJson.symbol
Here's what I've done so far:
import Autocomplete from 'react-native-autocomplete-input';
import React, { Component } from 'react';
import { StyleSheet, Text, TouchableOpacity, Platform,
ScrollView, View, ActivityIndicator,
} from 'react-native';
class AutocompleteExample extends Component {
constructor(props) {
super(props);
this.state = {
symbols: [],
query: '',
};
}
searchSymbol(query) {
if (query === '') {
return [];
}
const { symbols } = this.state;
const url = `https://api.iextrading.com/1.0/ref-data/symbols`;
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
symbols:responseJson.symbol,
});
})
.catch((error) => {
console.error(error);
});
return symbols;
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
const { query } = this.state;
const symbols = this.searchSymbol(query);
return (
<ScrollView>
<View style={styles.MainContainer}>
<Text style={{fontSize: 12,marginBottom:10}}> Type your favorite stock</Text>
<Autocomplete
autoCapitalize={true}
containerStyle={styles.autocompleteContainer}
data={symbols}
defaultValue={query}
onChangeText={text => this.setState({ query: text })}
placeholder="Enter symbol"
renderItem={({ symbol }) => (
<TouchableOpacity onPress={() => this.setState({ query: symbol })}>
<Text style={styles.itemText}>
{symbol}
</Text>
</TouchableOpacity>
)}
/>
</View>
</ScrollView>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
paddingTop: (Platform.OS === 'ios') ? 20 : 20,
padding: 5,
},
autocompleteContainer: {
borderWidth: 1,
zIndex:999,
borderColor: '#87ceeb',
},
itemText: {
fontSize: 17,
color:'#000000',
}
});
module.exports = AutocompleteExample
I don't see any error on the console and the api request is working correctly, I just can't access symbols const Do I have to render something like cloneWithRows(responseJson.symbols) ? Thanks

First of all, the searchSymbol method should be either binded in the component constructor, or declared as a class property. Otherwise, "this" will not point to the component instance.
Then, it seems that your state does not have an isLoading property, but you use it in your render function.
What you should probably do is call your asynchronous searchSymbol method in the componentDidMount lifecycle method. When the promise of the fetch resolves, you should put the result in the state as well as put the isLoading boolean to false. Then your component will re-render with the now available data.

Related

set Multiple state Id for custom component in React Native

I have implemented custom inputBox component. So When I am using this component first time then it is working fine and when I am using multiple time in one page then data is prepopulate to next component.
Custom component:
import React, { createRef } from 'react';
import {
View,
TextInput,
Alert,
Text,
StyleSheet
} from "react-native";
class BoxInput extends React.Component {
constructor(props) {
super(props)
this.state = {
digit1: '',
digit2: '',
digit3: '',
...props
}
this.digit1Ref = createRef()
this.digit2Ref = createRef()
this.digit3Ref = createRef()
}
componentDidMount() {
this.digit1Ref.current.focus()
}
componentDidUpdate(prevProps) {
if (this.state.digit1 && this.state.digit2 &&
this.state.digit3
}
saveText(text, key) {
this.setState({ ...this.state, [key]: text }, () => {
if (text) {
key == 'digit1' ? this.digit2Ref.current.focus() : null
key == 'digit2' ? this.digit3Ref.current.focus() : null
key == 'digit3'
}
const boxInputValue = this.state.digit1 + this.state.digit2 + this.state.digit3
this.props.onBoxInput(boxInputValue)
});
}
render() {
return (
<>
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit1Ref} style={styles.boxStyle} value={this.state.digit1} onChangeText={(text) => this.saveText(text, 'digit1')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit2Ref} style={styles.boxStyle} value={this.state.digit2} onChangeText={(text) => this.saveText(text, 'digit2')} />
<TextInput maxLength={1} keyboardType={'numeric'} ref={this.digit3Ref} style={styles.boxStyle} value={this.state.digit3} onChangeText={(text) => this.saveText(text, 'digit3')} />
</>
)
}
}
const styles = StyleSheet.create({
boxStyle: {
marginTop: 20,
height: 57,
width: 50,
borderRadius: 10,
borderWidth: 1,
borderColor: '#F1F5F9',
backgroundColor: '#F1F5F9',
fontSize: 20,
lineHeight: 40,
paddingHorizontal: 15,
textAlign: 'center'
}
})
export default BoxInput;
import React, { createRef } from 'react';
import styles from './style';
import {
View,
TextInput,
Alert
} from "react-native";
import { connect } from "react-redux";
import * as Animatable from 'react-native-animatable';
import BoxInput from "../../../../md-components/atoms/boxinput"
class MPINScreen extends React.Component {
constructor(props) {
super(props)
this.state = {
confirmMpinEnable: true,
...props
}
this.codes = [{
value: '+91',
}]
}
componentDidUpdate(prevProps) {
if (this.state.mpinValue.split("").length == 3 &&
prevProps.success_msg != this.props.success_msg && this.props.success_msg == 'verified') {
NavigationService.navigate(this.props.navigation, 'MPINVerifyOnboarding')
}
}
handleSubmit = () => {
if (this.state.mpinValue != this.state.confirmMpinValue) {
Alert.alert(
"Error",
"MPIN is not machted",
[
{ text: "OK" }
],
{ cancelable: false }
);
} else {
this.props.verifyMpin({
"mpin": this.state.mpinValue,
phoneNumber: this.props.mobileNumber
})
}
}
mpinConfirmation = () => {
if (this.state.mpinValue.split("").length != 6) {
Alert.alert(
"Error",
"Please insert 6 digit mpin",
[
{ text: "OK" }
],
{ cancelable: false }
);
}else{
this.setState({
confirmMpinEnable: false,
});
}
}
mpinText = (args) => {
this.setState({
mpinValue: args,
});
}
confirmMpinText = (args) => {
this.setState({
confirmMpinValue: args,
});
}
render() {
return (
<>
<HeaderComponent backgroundColor="#E5E5E5" showLeftIcon={true} showRightIcon={false} />
<View style={styles.container}>
<Text style={[styles.textInfo, styles.textTitle]}>We are almost there!</Text>
<View style={styles.imageWrapper}>
<Animatable.View animation="slideInDown" iterationCount={1} style={styles.centerIconWrap}>
<Image style={styles.centerIcon} source={mpin_card} />
</Animatable.View>
</View>
{this.state.confirmMpinEnable ?
<Text style={[styles.textInfo]}>Setup your MPIN</Text> : <Text style={[styles.textInfo]}>Confirm your MPIN</Text>
}
{this.state.confirmMpinEnable ?
<View style={styles.rowWrap}>
<BoxInput id="catFood1" onBoxInput={this.mpinText} />
</View>:
<View style={styles.rowWrap}>
<BoxInput id="catFood2" onBoxInput={this.confirmMpinText} />
</View>
}
<View style={styles.marginBottom}>
<Text style={[styles.mpinNote]}>M-PIN is a short 6-digit PIN that you have to set for</Text>
<Text style={[styles.mpinNote]}>our mandatory Two-Factor Authentication</Text>
</View>
<View style={styles.bottomBtnSyle}>
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleBack}>{"Back"}</Button>
</View>
{this.state.confirmMpinEnable ?
<View style={styles.multipleBtnStyle}>
<Button onPress={this.mpinConfirmation} >{"Confirm"}</Button>
</View> :
<View style={styles.multipleBtnStyle}>
<Button onPress={this.handleSubmit} >{"Save & Continue"}</Button>
</View>
}
</View>
</View>
</>
)
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MPINScreen);
when I am click on confirm button then hide and display . But in second component data is prepopulating which i was inserted.
in this screen shot data is prepopulate but i want this empty, Because user has to insert again. but it is taking same value from previous state. how we can use multiple time same component in one page.
General idea:
Create a property in MPINScreen state that is changing (incrementing) every attempt (you can call it attempt) and pass it as prop to BoxInput.
In BoxInput create a reset function (that will clean the values of the text inputs and focus the first input). On componentDidUpdate check if attempt prop changed. If true - save the new value in BoxInput state and call "reset".

Can't find variable when adding data to Flatlist from json in React-Native

I'm new to react native, so please be kind! I am trying to populate a Flatlist using a JSON.
Below is my JSON data
{
"h1":{
"baseprice":899,
"description":"Upto Waist length Hair",
"imageUrl":"https://i.imgur.com/0IgYzAv.jpg'",
"price":799,
"time":"25 min",
"title":"Nourishing Hair Spa",
"type":"Service"
},
"h2":{
"baseprice":899,
"description":"Touch Up of length less than 4 inches",
"imageUrl":"https://i.imgur.com/q7ts4PZ.jpg",
"price":799,
"time":"45 min",
"title":"INOA Root Touch Up",
"type":"Service"
}
}
Here is the code that I used to push the JSON data in to my Flatlist
export default class Office extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch("https://stylmate1.firebaseio.com/hair.json")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson,
});
console.log(dataSource);
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, paddingTop: 20 }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={(item) => <Text>{item.title}</Text>}
/>
</View>
);
}
}
As soon as I refresh the App I get an error
Can't find variable : dataSource
But if I console.log(responseJson); then I get the complete JSON object.
I don't know what am I doing wrong here. Please help me in fixing this.
Your FlatList is supposed to look like this:
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item[1].title}</Text>}
/>
</View>
);
You have to destructure the item in order to use it.
Output:
Working Example code:
import React, { useState, useEffect } from 'react';
import { Text, View, FlatList, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { Card } from 'react-native-paper';
export default function App() {
const [dataSource, setData] = useState([]);
useEffect(() => {
fetch('https://stylmate1.firebaseio.com/hair.json')
.then((response) => response.json())
.then((responseJson) => {
setData(responseJson);
console.log(responseJson);
})
.catch((error) => {
console.error(error);
});
}, []);
return (
<View style={styles.container}>
{dataSource ? (
<FlatList
data={Object.entries(dataSource)}
renderItem={({ item }) => (
<View style={{ padding: 10 }}>
<Card>
<Text style={styles.paragraph}>{item[1].title}</Text>
</Card>
</View>
)}
/>
) : null}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
Expo Snack Live Demo
The Error happens because you are trying to log dataSource which is wrong it should be this.state.dataSource.
console.log(dataSource);
change it to
console.log(this.state.dataSource);
in your .then() block
firstly,
console.log(dataSource);
should change to
console.log(this.state.dataSource);
However, you may not get the correct console.log since set state is async. You get better and accurate answer with responseJson
Secondly, flatList requires an array of objects structure, you need to convert them using the following methods. I moved your "h1", and "h2" into the object and label them as key.
const original = {
"h1":{
"baseprice":899,
"description":"Upto Waist length Hair",
"imageUrl":"https://i.imgur.com/0IgYzAv.jpg'",
"price":799,
"time":"25 min",
"title":"Nourishing Hair Spa",
"type":"Service"
},
"h2":{
"baseprice":899,
"description":"Touch Up of length less than 4 inches",
"imageUrl":"https://i.imgur.com/q7ts4PZ.jpg",
"price":799,
"time":"45 min",
"title":"INOA Root Touch Up",
"type":"Service"
}
}
const newArray = Object.keys(original).map( key => ({...original[key], key }))
console.log(newArray)

why i got [object object ]

import React, { Component } from "react";
import { Button, View ,Text ,StyleSheet, FlatList, ScrollView} from "react-native";
import DateTimePicker from "react-native-modal-datetime-picker";
import moment from 'moment'
import addDays from 'date-fns/addDays'
import Modal from 'react-native-modal';
export default class MExample extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
day:[],
isDateTimePickerVisible: false,
choseDate:'',
visibleModal: false,
lists:''
};
}
showDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: true });
};
hideDateTimePicker = () => {
this.setState({ isDateTimePickerVisible: false });
};
handleDatePicker = ( date ) => {
// console.log("A date has been picked:", date); here date come correctly
this.setState ({
choseDate: 'Subscription start date ' + moment(date).format('MMMM, Do YYYY '),
})
this.hideDateTimePicker();
};
hideListPicker = () => {
this.setState({ visibleModal: null ,list:[] });
};
handleListPicker = ( list ) => {
console.log(list.toString())
this.setState ({
lists: 'list of start dates ' + list
})
this.hideListPicker();
};
getListViewItem = (item) => {
let newList = this.state.list;
if (newList.includes(item)) {
let index = newList.indexOf(item);
newList.splice(index,1);
} else {
newList.push(item);
}
this.setState({
list: newList,
});
}
renderModalContent = () => (
<View>
<Text style={styles.textBox} onPress={this.showDateTimePicker}>Select Date</Text>
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicker}
onCancel={this.hideDateTimePicker}
minimumDate = {new Date()}
maximumDate = {addDays(new Date(), 30)}
/>
<View style = {{backgroundColor:'white'}}>
<View>
<FlatList horizontal={true}
data = {[{day: '1'},{day: '2'}, {day: '3'},{day: '4'}, {day: '5'},{day: '6'},{day: '7'}]}
renderItem={({item, index}) =>
<Text style={styles.textBox} key={index}
onPress={this.getListViewItem.bind(this, item.day)}>{item.day}
</Text>}
/>
<ScrollView
style = {{marginHorizontal: 20}}
horizontal={true}
>
{
this.state.list.map((l, index) => {
return(
index !== this.state.list.length - 1 ? <Text style={{fontSize:30, color:'red'}}>{l}, </Text> : <Text style={{fontSize:30, color:'red'}}>{l}</Text>
)
})
}
</ScrollView>
</View>
</View>
<Button
onPress={this.handleListPicker}
title="Submit"
/>
</View>
);
render() {
return (
<>
<Text style={{fontSize:20}}>Frequency</Text>
<View style={styles.container} >
<Text style={styles.textBox} onPress={() => this.setState({ visibleModal: 'default' })}>Weekly </Text>
</View>
<Text style={{fontSize:20, color:'black', textAlign:'center'}}>{this.state.choseDate} </Text>
<Text style={{fontSize:20, color:'black', textAlign:'center'}}>{this.state.lists} </Text>
<Modal isVisible={this.state.visibleModal === 'default'}
onBackButtonPress={() => this.setState({ visibleModal: null, list:[] }, )}>
{this.renderModalContent()}
</Modal>
</>
);
}
}
const styles = StyleSheet.create({
container:{
flexDirection:'row',
flexWrap:'wrap',
justifyContent:'center',
},
textBox :{
fontSize:20,
textAlign:'center',
borderWidth: 1,
borderRadius: 12,
borderColor: "#CBCBCB",
margin:10,
padding:5,
backgroundColor:'#a0a3a3'
},
});
i have created modal here user select date list and after submit i clear list in setState
why i get [object object] in console
export default class MExample extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
visibleModal: false,
lists: ''
};
}
hideListPicker = () => {
this.setState({ visibleModal: null ,list:[] });
};
handleListPicker = ( list ) => {
console.log(list.toString())
// [object objcet]
this.setState ({
lists: 'list of start dates ' + list
})
this.hideListPicker();
};
render(){
return(
// jsx <Text>{this.state.lists} </Text> // [object object]
<Button onPress={this.handleListPicker}
title="Submit"
/>
)
}
Use JSON.stringify instead .toString
This question might help you What's the difference in using toString() compared to JSON.stringify()? understand the difference
let x = {a: 123, b: 321};
console.log("toString", x.toString());
console.log("stringified", JSON.stringify(x));
If you're having a circular JSON you might like to visit How can I print a circular structure in a JSON-like format? to see how to console such JSONs
It is because you are passing event as parameter on Button click, which is an object. Now when you use list.toString(), it will convert this event Object into String and show you [Object Object].
You can verify it by using
console.log("data = ",list)
instead of
console.log(list.toString())
In your case, just remove the toString() function to get what you need.
SIDE NOTE: When use console.log in browser environment, when your object has nested levels, you might get something like
> a: [...]
After clicking > in the web console, you will see the value, but this value is determined at the moment you clicked, not the moment it ran through your console.log.
The best way to get the value at the time you logged it, use console.log(JSON.stringify(object)) instead.
To format the JSON output, passing params to stringify function like below:
console.log(
JSON.stringify
(
obj, // the object you want to log
null,
2 // the indent counts by spaces for each level
)
)
Because method toString returns it. For print object data just pass object to console.log method like console.log(list)

Understanding React Natives setState and componentWillMount from FlatList

So I'm trying to make a simple application with expo and expo audio that will generate a list of audio buttons and text. But I cannot figure out how react works regarding redrawing the setState OUTSIDE componentWillMount and how to remake a soundobject with a new URI
So right now it will work but only playing the FIRST uri, I assume this is because the object still exists.
And it will not change the state of the button, I know this is because react cant see its changing for some reason from FlatList
It works outside of it, if I only make one button in renders view.
FlatList will render the setStates if I use LegacyImplementation=true .. But Im warned this is deprecated. And it renders it for all buttons at the same time
This is my handlerClass:
export class TSSGetter extends React.Component {
constructor(props){
super(props);
this.state ={
isLoading: true,
playingStatus: "Play"
}
}
retrieveData() {
const endpoint = 'http://127.0.0.1:3333/get'
const data = {
"userId": "123412341234",
"hmac": "detteerikkeenrigtighmac"
}
return new Promise((resolve, reject) => {
fetch(endpoint, {
method: 'POST',
headers: {
'Accept': 'application/json',
'content-type':'application/json'
},
body: JSON.stringify(data)
})
.then((resp) => {
console.log('hej return')
return resp.json();
})
.then((resp) => {
resolve(resp);
console.log('resp')
}).catch(function(error) {
console.log(error,'naeh')
});
});
}
componentDidMount(){
this.retrieveData()
.then((resp) => {
var pages = resp.books.contentObjects
pages.map((userData) => {
console.log('superduper pages', userData.contentObjectId)
})
this.setState({
isLoading: false,
dataSource: resp.books.contentObjects,
dataroot: resp.books
});
}).catch((err) => {
//handle error
console.log("Api call error2");
alert(err);
})
}
async _playRecording(AudioURL) {
console.log(AudioURL)
const { sound } = await Audio.Sound.createAsync(
{uri: AudioURL},
{
shouldPlay: true,
isLooping: true,
},
this._updateScreenForSoundStatus,
);
this.sound = sound;
this.setState({
playingStatus: 'playing'
});
}
_updateScreenForSoundStatus = (status) => {
if (status.isPlaying && this.state.playingStatus !== "playing") {
this.setState({ playingStatus: "playing" });
} else if (!status.isPlaying && this.state.playingStatus === "playing") {
this.setState({ playingStatus: "donepause" });
}
};
async _pauseAndPlayRecording() {
if (this.sound != null) {
if (this.state.playingStatus == 'playing') {
console.log('pausing...');
await this.sound.pauseAsync();
console.log('paused!');
this.setState({
playingStatus: 'donepause',
});
} else {
console.log('playing...');
await this.sound.playAsync();
console.log('playing!');
this.setState({
playingStatus: 'playing',
});
}
}
}
_syncPauseAndPlayRecording() {
if (this.sound != null) {
if (this.state.playingStatus == 'playing') {
this.sound.pauseAsync();
} else {
this.sound.playAsync();
}
}
}
_playAndPause = (AudioURL) => {
console.log(AudioURL)
switch (this.state.playingStatus) {
case 'Play':
this._playRecording(AudioURL);
break;
case 'donepause':
case 'playing':
this._pauseAndPlayRecording();
break;
}
}
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
const styling = {
flex: 1,
paddingTop:10
// flexDirection: 'row'
}
const data = this.state.dataroot;
return(
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) =>
<View>
<TouchableOpacity style={styles.button} onPress={() => this._playAndPause(item.AudioURL)}>
<Text style={styles.buttonText}>
{this.state.playingStatus}+ {item.contentObjectId}
</Text>
</TouchableOpacity>
<Text style={styles.description}>
{item.text},
</Text>
</View>
}
keyExtractor={(item, index) => item.contentObjectId}
/>
</View>
);
}
}
UPDATE: setting extraData={this.state} in flatlist updates the button.. But all the buttons. How do I change the scope of the button?
You could create a specific component for the items in the FlatList. Each of the items will then have their own state.
import React, { Component } from "react";
import { StyleSheet, Text, View } from "react-native";
import { FlatList } from "react-native-gesture-handler";
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<FlatList
keyExtractor={(item, index) => index.toString()}
data={[1, 2, 3, 4, 5]}
renderItem={({ item }) => <Sound />}
/>
</View>
);
}
}
class Sound extends Component {
constructor() {
super();
this.state = {
status: "IDLE"
};
}
onChangeState = value => {
this.setState({
status: value
});
};
render() {
const { status } = this.state;
return (
<View style={{width: 200,paddingVertical: 10}}>
<Text>Status: {status}</Text>
<View style={{ flex: 1,flexDirection: "row", justifyContent: "space-between" }}>
<Text onPress={() => this.onChangeState("PLAYING")}>PLAY</Text>
<Text onPress={() => this.onChangeState("STOPPED")}>STOP</Text>
<Text onPress={() => this.onChangeState("PAUSED")}>PAUSE</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 100,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center"
}
});
I checked out in the docs, here, and I saw that it will re-render just if you pass the state prop, see this explanations:
By passing extraData={this.state} to FlatList we make sure FlatList itself will re-render when the state.selected changes. Without setting this prop, FlatList would not know it needs to re-render any items because it is also a PureComponent and the prop comparison will not show any changes.

React Native Fetch works only on second click

I do app on React Native. The problem is next :
OnPress some element i am trying make request to my server and log answer.
When I click button first time - my log do not show anything , but on second click I see response in the console.
import React from 'react'
import { View, Text, StyleSheet, TextInput , TouchableNativeFeedback , AsyncStorage } from 'react-native'
import {connect} from 'react-redux'
import * as pageActions from '../action/index'
import { bindActionCreators } from 'redux'
import api from '../api'
class Login extends React.Component {
constructor(props){
super(props);
this.state = {
loginAttempt : false,
email : 'admin#mail.ru',
password : 'password',
token : ''
}
}
loginAttempt() {
let email = this.state.email;
let password = this.state.password;
api.login(email,password)
}
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Email"
style={{height: 50, borderColor: 'gray', borderWidth: 1}}
onChangeText={(value) => this.setState({email : value})}
/>
<TextInput
placeholder="Password"
style={{height: 50, borderColor: 'gray', borderWidth: 1}}
onChangeText={(value) => this.setState({password : value})}
/>
<TouchableNativeFeedback
style={!this.state.loginAttempt ? {'opacity' : 1} : {'opacity' : 0}}
onPress={() => this.loginAttempt()}>
<View>
<Text>Try login</Text>
</View>
</TouchableNativeFeedback>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
}
}
)
My fetch function
login(email,password, callback) {
const API_HEADERS = {
'Accept' : `application/json`,
'Content-Type' : `application/json`
};
let user = {};
user.email = email;
user.password = password;
fetch(`http://myIp:3000/auth/login`, {
method : 'post',
headers : API_HEADERS,
body : JSON.stringify(user)
})
.then((response) => {
if (response.ok) {
return response.json();
} else {
alert(`Wrong data`)
}
})
.then((responseData) => {
console.log(responseData)
})
}
Also wanna add that I using Genymotion as android emul.Another strange thing is that when I press my button first time - nothing happens,but when i press Reload JS , before the component will be unmount , I see my responceData in a console
You should update state, when promise resolved.
.then((responseData) => {
this.setState({
token: responseData.token
});
})
Use catch method:
.then().catch(e => console.log("error: ", e))
Also, where is your alert function? react-native has Alert module.
Alert.alert('any message text');
article about fetch
and this is article using fetch in react-native
Another strange thing is that when I press my button first time
This is very like related to focus.
Try setting keyboardShouldPersistTaps = true for TouchableNativeFeedback

Resources