Unable to get data using ReactNative fetch - react-native

I'm trying to fetch data from an API(I created my own Rest API using JSON-server). But I'm unable to fetch anything. however, I'm able to see the data when I navigate to localhost:3000/events. There's no other error in my app. I only get this when I run the app it says network request failed. All the components are working fine. Just not getting the data. I've tried some other online APIs still not getting any response. I've tried with async/await. I'm using the app with IOS but have tried with Andriod as well. Same problem occurs. Attaching the code snippets. Any help would be highly appreciated. Thanks
Created the getEvent Function:
const { manifest } = Constants;
const api = manifest.packagerOpts.dev
? manifest.debuggerHost.split(`:`).shift().concat(`:3000`)
: `api.example.com`;
const url = `http://${api}/events`;
export function getEvents() {
return fetch(url)
.then(response => response.json())
.then(events => events.map(e => ({ ...e, date: new Date(e.date) })))
}
Using it inside the componentDidMount
componentDidMount() {
// getEvents().then(events => this.setState({ events }));
setInterval(() => {
this.setState({
events: this.state.events.map(evt => ({
...evt,
timer: Date.now()
}))
});
}, 1000);
this.props.navigation.addListener("didFocus", () => {
getEvents().then(events => this.setState({ events }));
});
}
Data that I'm trying to fetch.
{
"events": [
{
"title": "Demo a new app",
"date": "2020-03-29T13:45:18.000Z",
"id": "001c9b6d-00a9-465c-a2d3-afb7176a0a87"
}
]
}

you can use axios as of fetch , it is also used to hit API's and get response from them , and it is simple and easy way as compare to fetch.
run npm i react-native-axios on your project root floder to install the library and import it and use it , here is an example of axios , in which the user will login to screen and will hit the login API , the user enter their credentials and if they are correct as in API then user will get response or user will login successfully.
import axios from "axios";
export default class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: "",
}
};
onPresssighnin = () => {
var data = {
//parameters to pass API
Email: this.state.email,
Password: this.state.password,
};
axios
.post(" insert API url here", data, {
"Content-Type": "application/json"
})
.then(
response => {
//get response here
alert(JSON.stringify(response))
},
error => {
//get errormessage here
errormessage = error.Message;
alert(errormessage);
}
);
}
};
render() {
return (
<View style={styles.logoContainer}>
<Input
borderless
placeholder="Email"
onChangeText={email => this.setState({ email })}
iconContent={
<Icon
size={16}
color={ditsTheme.COLORS.ICON}
name="ic_mail_24px"
family="DitsExtra"
style={styles.inputIcons}
/>
}
/>
<Input
password
borderless
placeholder="Password"
onChangeText={password =>this.setState({ password })}
iconContent={
<Icon
size={16}
color={ditsTheme.COLORS.ICON}
name="padlock-unlocked"
family="DitsExtra"
style={styles.inputIcons}
/>
}
/>
<Button
color="primary"
style={styles.createButton}
onPress={this.onPresssighnin} >
<Text bold size={14} color={ditsTheme.COLORS.WHITE}>
SIGN IN
</Text>
</Button>
</View>
)
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'rgb(32, 53, 70)',
flexDirection: 'column',
},
buttonText: {
textAlign: 'center',
color: 'rgb(32, 53, 70)',
fontWeight: 'bold',
fontSize: 18
}
})
Feel free for Doubts.

Related

React Native Workflow, handle 429 erros and data

im looking for a bit of guideness here, im working on a RN app with redux and everytime i enter a new screen on the app, must likely i have a "callinitialData" function inside my useEffect(), using axios to fetch api data to be dispatch() to the redux state.
Everything works but whenever i jump from screen to screen to fast, sometimes i get a 429 error of to many request, so i just setup the redux-persist hoping that would help reduce the amount of request,in my mind thinking that if my api data is equal to my local data, that request wouldnt be necessary to be made.
However it stays the same so i was thinking what would be the best aproach here, on login try to fetch all the data at once > store it at asyncstorage and redux, and fetch that on each screen ?
how would i be able then, if i fetch all the data on login, receive the new data sets from the api in real time?
App functionality -
Edit Profile (img, pass, email, name)
Data Forms (requeast X, submit data, edit forms)
Chat by contacts / create Group chat
Code Example
const ChatScreen = ({ auth: { user }, getChatContacts, chat: { contacts }, navigation }) => {
useEffect(() => {
getChatContacts();
}, []);
const onChatUser = async (_id, name, roomID) => {
console.log(_id, name, roomID, contacts.payload.clone)
navigation.navigate( "Message", {
_id, name, chatRoomId: roomID, allUsers: contacts.payload.clone
});
}
const renderItem = ({ item , index } ) => {
let userName = "";
item.users.map((users, index) => {
let idToCheck = users.toString() !== user._id.toString() ? users : false;
if (idToCheck) {
let getOneUser = contacts.payload.clone.find(x => x._id === idToCheck);
userName += "" + getOneUser.name + ", ";
}
})
return (<TouchableOpacity key={item._id} onPress={() => onChatUser(item._id, item.name, item.roomID)}>
<View style={styles.chatContainer}>
<FontAwesome name="user-circle-o" size={50} color="#000000"/>
<Text style={styles.chatTitle}>{ ((userName).length > 32) ?
(((userName).substring(0,32-3)) + '...') :
userName }</Text>
<FontAwesome name="angle-right" size={25} color="#000000"/>
</View>
</TouchableOpacity>)
};
return (
<SafeAreaView style={styles.container}>
<TextInput
autoCapitalize="none"
autoCorrect={false}
clearButtonMode="always"
placeholder="Search friend"
style={styles.chatsearch}
/>
{contacts ?
(<FlatList
data={contacts.payload.allContact}
renderItem={(item, index) => renderItem(item, index)}
keyExtractor={item => item.id}
style={styles.FlatListContainer}
/>) : (<Text style={styles.FlatListContainer}></Text>)
}
</SafeAreaView>
);
}
const styles = StyleSheet.create({});
ChatScreen.propTypes = {
isAuthenticated: PropTypes.bool,
auth: PropTypes.object,
};
const mapStateProps = state => ({
auth: state.auth,
chat: state.chat
});
export default connect(mapStateProps, {getChatContacts} )(ChatScreen);
Redux Action
export const getChatContacts = () => async dispatch => {
const config = {
header: {
"Content-Type": "application/json"
}
}
try {
const res = await axios.get(API_LINK +"/users/getChatContacts",);
dispatch({
type: GET_CONTACT_CHAT,
payload: res.data
});
} catch (err){
console.log(err)
dispatch({
type: ERROR_FAMILY_PARENT,
payload: { msg: err.response, status: err.response}
});
}
};

React Native Gifted Chat + Firestore not showing messages correctly?

I am trying to create a chat feature in my react native app. I am using react-native-gifted-chat and saving the messages in firestore. Here is the behavior that is occurring:
When I send a message, ALL the messages re render, some of them are duplicates, as you can see I only have 3 messages sent so far, but all these duplicates are making me wonder why the entire thing is re-rendering and why there are duplicates when it does re-render.
The code:
class Chat extends React.Component {
constructor(props) {
super(props)
this.state = {
messages: [],
currentUser: null,
isLoading: true,
messageID: ""
}
}
//---------------------------------------------------------------
async componentDidMount (){
// get user info from firestore
let userUID = Firebase.auth().currentUser.uid
await Firebase.firestore().collection("users").doc(userUID).get()
.then(doc => {
data = doc.data()
this.setState({
currentUser: {
name: data.username,
avatar: data.profilePic,
_id: doc.id,
},
})
})
const messages = []
await Firebase.firestore().collection("chat")
.orderBy("createdAt", "desc")
.limit(50)
.onSnapshot(querySnapshot => {
querySnapshot.forEach((res) => {
const {
user,
text,
createdAt,
} = res.data();
messages.push({
key: res._id,
user,
text,
createdAt,
});
})
this.setState({
messages,
isLoading: false,
});
})
}
//Load 50 more messages when the user scrolls
//
//Add a message to firestore
onSend = async(message) => {
await Firebase.firestore().collection("chat")
.add({
user: {
_id: this.state.currentUser._id,
name: this.state.currentUser.name,
avatar: this.state.currentUser.avatar,
},
})
.then(ref => this.setState({messageID: ref.id}))
await Firebase.firestore().collection("chat")
.doc(this.state.messageID)
.set({
_id: this.state.messageID,
text: message[0].text,
createdAt: message[0].createdAt
}, { merge: true })
}
render() {
if(this.state.isLoading){
return(
<View style = {{backgroundColor: '#000000', flex: 1}}>
<ActivityIndicator size="large" color="#9E9E9E"/>
</View>
)
}
return (
<View style={{backgroundColor: '#000000', flex: 1}}>
<GiftedChat
showUserAvatar={true}
renderUsernameOnMessage={true}
messages={this.state.messages}
onSend={message => this.onSend(message)}
scrollToBottom
/>
</View>
)
}
}
Some notes:
Every time the component mounts, the messages array pushes the messages to the state array.
The component mounts when I send a message, thus re-rendering the array of messages
Each message ID is unique and generated by firebase using "Add"
Let me know how I can fix this issue! thanks
Duplication is because of just single line
const messages = []
Move this line inside listener, i.e.onSnapShot()
await Firebase.firestore().collection("chat")
.orderBy("createdAt", "desc")
.limit(50)
.onSnapshot(querySnapshot => {
const messages = []
// rest of your code which is having forEach loop
});
The issue was that messages object was created only once when the component loaded, and you were pushing elements to that object only.

The best way of tracking location in background using react-native + Expo in 2020

I want to create my own Endomono/Runtastic-like app using RN + expo (This app will be just for me, and I have android phone with pretty decent performance/battery life (Redmi note 7) so I don't worry about performance too much). I wanted to use all-in-one library for that, or just and library that allows me to execute some code each X seconds in background (and getAsyncLocation there). My point is just to send lat/lon data every X seconds to my backend HTTP django-rest-framework powered server.
I just spent whole day trying figure out any way to do that, I tried couple of libraries like this ones: react-native-background-geolocation, react-native-background-timer, react-native-background-job and few more. I followed step by step instalation guide, and I kept getting errors like: null is not an object (evaluating 'RNBackgroundTimer.setTimeout') .
I also tried this: I fixed some errors in this code (imports related), it seemed to work, but when I changed my GPS location using Fake GPS, and only one cast of didFocus functions appears in the console. Here's code:
import React from 'react';
import { EventEmitter } from 'fbemitter';
import { NavigationEvents } from 'react-navigation';
import { AppState, AsyncStorage, Platform, StyleSheet, Text, View, Button } from 'react-native';
import MapView from 'react-native-maps';
import * as Permissions from 'expo-permissions';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import { FontAwesome, MaterialIcons } from '#expo/vector-icons';
const STORAGE_KEY = 'expo-home-locations';
const LOCATION_UPDATES_TASK = 'location-updates';
const locationEventsEmitter = new EventEmitter();
export default class MapScreen extends React.Component {
static navigationOptions = {
title: 'Background location',
};
mapViewRef = React.createRef();
state = {
accuracy: 4,
isTracking: false,
showsBackgroundLocationIndicator: false,
savedLocations: [],
initialRegion: null,
error: null,
};
didFocus = async () => {
console.log("Hello")
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
AppState.addEventListener('change', this.handleAppStateChange);
this.setState({
error:
'Location permissions are required in order to use this feature. You can manually enable them at any time in the "Location Services" section of the Settings app.',
});
return;
} else {
this.setState({ error: null });
}
const { coords } = await Location.getCurrentPositionAsync();
console.log(coords)
const isTracking = await Location.hasStartedLocationUpdatesAsync(LOCATION_UPDATES_TASK);
const task = (await TaskManager.getRegisteredTasksAsync()).find(
({ taskName }) => taskName === LOCATION_UPDATES_TASK
);
const savedLocations = await getSavedLocations();
const accuracy = (task && task.options.accuracy) || this.state.accuracy;
this.eventSubscription = locationEventsEmitter.addListener('update', locations => {
this.setState({ savedLocations: locations });
});
if (!isTracking) {
alert('Click `Start tracking` to start getting location updates.');
}
this.setState({
accuracy,
isTracking,
savedLocations,
initialRegion: {
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.004,
longitudeDelta: 0.002,
},
});
};
handleAppStateChange = nextAppState => {
if (nextAppState !== 'active') {
return;
}
if (this.state.initialRegion) {
AppState.removeEventListener('change', this.handleAppStateChange);
return;
}
this.didFocus();
};
componentWillUnmount() {
if (this.eventSubscription) {
this.eventSubscription.remove();
}
AppState.removeEventListener('change', this.handleAppStateChange);
}
async startLocationUpdates(accuracy = this.state.accuracy) {
await Location.startLocationUpdatesAsync(LOCATION_UPDATES_TASK, {
accuracy,
showsBackgroundLocationIndicator: this.state.showsBackgroundLocationIndicator,
});
if (!this.state.isTracking) {
alert(
'Now you can send app to the background, go somewhere and come back here! You can even terminate the app and it will be woken up when the new significant location change comes out.'
);
}
this.setState({ isTracking: true });
}
async stopLocationUpdates() {
await Location.stopLocationUpdatesAsync(LOCATION_UPDATES_TASK);
this.setState({ isTracking: false });
}
clearLocations = async () => {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify([]));
this.setState({ savedLocations: [] });
};
toggleTracking = async () => {
await AsyncStorage.removeItem(STORAGE_KEY);
if (this.state.isTracking) {
await this.stopLocationUpdates();
} else {
await this.startLocationUpdates();
}
this.setState({ savedLocations: [] });
};
onAccuracyChange = () => {
const next = Location.Accuracy[this.state.accuracy + 1];
const accuracy = next ? Location.Accuracy[next] : Location.Accuracy.Lowest;
this.setState({ accuracy });
if (this.state.isTracking) {
// Restart background task with the new accuracy.
this.startLocationUpdates(accuracy);
}
};
toggleLocationIndicator = async () => {
const showsBackgroundLocationIndicator = !this.state.showsBackgroundLocationIndicator;
this.setState({ showsBackgroundLocationIndicator }, async () => {
if (this.state.isTracking) {
await this.startLocationUpdates();
}
});
};
onCenterMap = async () => {
const { coords } = await Location.getCurrentPositionAsync();
const mapView = this.mapViewRef.current;
if (mapView) {
mapView.animateToRegion({
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.004,
longitudeDelta: 0.002,
});
}
};
renderPolyline() {
const { savedLocations } = this.state;
if (savedLocations.length === 0) {
return null;
}
return (
<MapView.Polyline
coordinates={savedLocations}
strokeWidth={3}
strokeColor={"black"}
/>
);
}
render() {
if (this.state.error) {
return <Text style={styles.errorText}>{this.state.error}</Text>;
}
if (!this.state.initialRegion) {
return <NavigationEvents onDidFocus={this.didFocus} />;
}
return (
<View style={styles.screen}>
<MapView
ref={this.mapViewRef}
style={styles.mapView}
initialRegion={this.state.initialRegion}
showsUserLocation>
{this.renderPolyline()}
</MapView>
<View style={styles.buttons} pointerEvents="box-none">
<View style={styles.topButtons}>
<View style={styles.buttonsColumn}>
{Platform.OS === 'android' ? null : (
<Button style={styles.button} onPress={this.toggleLocationIndicator} title="background/indicator">
<Text>{this.state.showsBackgroundLocationIndicator ? 'Hide' : 'Show'}</Text>
<Text> background </Text>
<FontAwesome name="location-arrow" size={20} color="white" />
<Text> indicator</Text>
</Button>
)}
</View>
<View style={styles.buttonsColumn}>
<Button style={styles.button} onPress={this.onCenterMap} title="my location">
<MaterialIcons name="my-location" size={20} color="white" />
</Button>
</View>
</View>
<View style={styles.bottomButtons}>
<Button style={styles.button} onPress={this.clearLocations} title="clear locations">
Clear locations
</Button>
<Button style={styles.button} onPress={this.toggleTracking} title="start-stop tracking">
{this.state.isTracking ? 'Stop tracking' : 'Start tracking'}
</Button>
</View>
</View>
</View>
);
}
}
async function getSavedLocations() {
try {
const item = await AsyncStorage.getItem(STORAGE_KEY);
return item ? JSON.parse(item) : [];
} catch (e) {
return [];
}
}
if (Platform.OS !== 'android') {
TaskManager.defineTask(LOCATION_UPDATES_TASK, async ({ data: { locations } }) => {
if (locations && locations.length > 0) {
const savedLocations = await getSavedLocations();
const newLocations = locations.map(({ coords }) => ({
latitude: coords.latitude,
longitude: coords.longitude,
}));
savedLocations.push(...newLocations);
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(savedLocations));
locationEventsEmitter.emit('update', savedLocations);
}
});
}
const styles = StyleSheet.create({
screen: {
flex: 1,
},
mapView: {
flex: 1,
},
buttons: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
padding: 10,
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
},
topButtons: {
flexDirection: 'row',
justifyContent: 'space-between',
},
bottomButtons: {
flexDirection: 'column',
alignItems: 'flex-end',
},
buttonsColumn: {
flexDirection: 'column',
alignItems: 'flex-start',
},
button: {
paddingVertical: 5,
paddingHorizontal: 10,
marginVertical: 5,
},
errorText: {
fontSize: 15,
color: 'rgba(0,0,0,0.7)',
margin: 20,
},
});
If you know any way to easily complete my target (of sending simple HTTP GET with location from background of Expo + RN app to my DRF backend) please let me know.
If you're using Expo you can simply use expo-task-manager and expo-location to get background location updates.
Here's a simplified version that I'm using (and it's working for sure on Android) on the App I'm currently developing:
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import axios from 'axios';
const TASK_FETCH_LOCATION = 'TASK_FETCH_LOCATION';
// 1 define the task passing its name and a callback that will be called whenever the location changes
TaskManager.defineTask(TASK_FETCH_LOCATION, async ({ data: { locations }, error }) => {
if (error) {
console.error(error);
return;
}
const [location] = locations;
try {
const url = `https://<your-api-endpoint>`;
await axios.post(url, { location }); // you should use post instead of get to persist data on the backend
} catch (err) {
console.error(err);
}
});
// 2 start the task
Location.startLocationUpdatesAsync(TASK_FETCH_LOCATION, {
accuracy: Location.Accuracy.Highest,
distanceInterval: 1, // minimum change (in meters) betweens updates
deferredUpdatesInterval: 1000, // minimum interval (in milliseconds) between updates
// foregroundService is how you get the task to be updated as often as would be if the app was open
foregroundService: {
notificationTitle: 'Using your location',
notificationBody: 'To turn off, go back to the app and switch something off.',
},
});
// 3 when you're done, stop it
Location.hasStartedLocationUpdatesAsync(TASK_FETCH_LOCATION).then((value) => {
if (value) {
Location.stopLocationUpdatesAsync(TASK_FETCH_LOCATION);
}
});
It doesn't necessarily work with Expo, but if "eject" your project or start with the React Native CLI (via react-native init) then you could use an Android specific React Native "NativeModule" to accomplish your goal. I like using the react-native-location package, which has great support on iOS for background location updates, but on Android there is a bug currently. I put together an example project which has the necessary Android specific code inside a NativeModule you could use to start from:
https://github.com/andersryanc/ReactNative-LocationSample

How to navigate to another screen after axios action dispatch in reducer in react- native

I understand that this.props.isValidUser gets updated after action dispatches the axios promise. if the user is not valid is shows message. If the user is valid user, I want to navigate to another screen to enter pin. How do I navigate to another screen after I get axios result from action?
types.js
export const VALIDATE_USER = "VALIDATE_USER";
export const VALIDATE_PIN = "VALIDATE_PIN";
export const GET_ERRORS = "GET_ERRORS";
Reducer.js
import { VALIDATE_USER, VALIDATE_PIN, GET_ERRORS } from "../actions/types.js";
export default function (state = initialState, action) {
switch (action.type) {
case VALIDATE_USER:
return {
...state,
isValidUser: (action.payload == true) ? true : false,
Id: action.employeeId
};
case VALIDATE_PIN:
return {
...state,
isValidPin: action.payload,
action: "VALIDATE_PIN",
};
default:
return state;
}
}
action.js
import { GET_ERRORS, VALIDATE_USER, VALIDATE_PIN, } from "./types";
export const validateUser = (empId) => dispatch => {
axios.get(`${API}/api/Account/ValidateMobileAppUser?employeeId=${empId}`)
.then(res => {
dispatch({
type: VALIDATE_USER,
payload: res.data,
Id: empId,
});
})
.catch(err => {
dispatch({
type: VALIDATE_USER,
payload: false,
Id: empId
});
});
};
Login.js
import PropTypes from "prop-types";
import { validateUser } from "../actions/authActions";
class Login extends PureComponent {
constructor() {
super();
this.state = {
employeeId: "",
pin: "",
isValidUser: false,
};
this.onValidateUser = this.onValidateUser.bind(this);
this.onEmployeeId = this.onEmployeeId.bind(this);
}
onEmployeeId(employeeId) {
this.setState({ employeeId });
}
onValidateUser() {
this.props.validateUser(this.state.employeeId);
}
render() {
const { loading } = this.props.loading;
return (
<KeyboardAvoidingView style={styles.login} >
<ScrollView showsVerticalScrollIndicator={false}>
<Block padding={[10, theme.sizes.base * 2]} onPress={Keyboard.dismiss}>
<Block middle>
<Input
placeholder={this.state.placeholder}
keyboardType={this.state.keyboardType}
style={[styles.input]}
value={this.state.employeeId}
onChangeText={this.onEmployeeId}
/>
{(this.props.isValidUser == false) ? (
<Text center style={{ color: "#C00000", marginTop: 15, fontSize: 14 }}>
Employee Id not registered. Please contact HR.
</Text>
) : ""}
<Button
gradient
style={styles.loginButton}
onPress={this.onValidateUser}
>
<Text white center>
Login
</Text>
</Button>
</Block>
<Button
onPress={() => this.onGoToStep(1)}
style={{
borderWidth: 1,
borderRadius: 30,
borderColor: "#E46932"
}}
>
<Text gray caption center style={{ color: "#E46932" }}>
Don't have an account? Sign Up
</Text>
</Button>
</Block>
</ScrollView>
</KeyboardAvoidingView>
);
}
}
Login.propTypes = {
validateUser: PropTypes.func.isRequired,
errors: PropTypes.object.isRequired
};
function reducerCallback(state, ownProps) {
if (state.auth.isValidUser == true) {
ownProps.navigation.navigate("mPin", { Id: state.auth.employeeId, type: "LOGIN" });
}
}
const mapStateToProps = (state, ownProps) => ({
auth: reducerCallback(state, ownProps),
isValidUser: state.auth.isValidUser,
errors: state.errors
});
export default connect(
mapStateToProps,
{
validateUser,
}
)(Login);
this.props.isValidUser == false tells me if the user is valid or not. But if the user is valid I'm navigating to another screen using reducerCallback() function. I'm not aware if this is the correct way to do so. My question is how to I navigate to another screen after I get return result from async axios action and How to I set local state using setState when I get callback from axios dispatch. Please guide
Try to below code:
login.js:
onValidateUser() {
this.props.validateUser({
empId: this.state.employeeId,
onSuccess: () => {
//Navigate to other screen
},
onFailure: () => {
//Alert error message
},
});
}
Action.js:
export const validateUser = ({empId, onSuccess, onFailure}) => dispatch => {
axios
.get(
`${API}/api/Account/ValidateMobileAppUser?employeeId=${empId}`
)
.then(res => {
dispatch({
type: VALIDATE_USER,
payload: res.data,
Id: empId,
});
onSuccess();
})
.catch(err => {
dispatch({
type: VALIDATE_USER,
payload: false,
Id: empId
});
onFailure()
});
};

React-Native error setState used in arrow function

I know was a thousand such questions relating to this same issue, but I've already exhausted ideas what might cause it in my case :/
I'm trying to update variable when after getting response from API.
I already changed all functions to use arrow function but I keep getting this error:
this.setState is not a function
and I can't find error in my code.
Can anyone see what's wrong?
app/routes/users/login/view.js
const UsersLoginView = (props) => {
let email = '';
this.state = {
textError: '',
inputError: false,
}
login = (event) => {
device_info = {
UUID: DeviceInfo.getUniqueID(),
brand: DeviceInfo.getBrand(),
model: DeviceInfo.getModel(),
system: DeviceInfo.getSystemName(),
system_version: DeviceInfo.getSystemVersion(),
timezone: DeviceInfo.getTimezone(),
locale: DeviceInfo.getDeviceLocale(),
}
fetch("my url", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
device: device_info
})
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
textError: 'SUCCESS',
inputError: false
});
})
.catch(error => {
this.setState({
textError: error.message,
inputError: true
});
})
.done();
},
updateEmail = (text) => {
email = text
}
return (
<Container>
<Content>
<Text style={{fontWeight: 'bold'}}>
User
</Text>
<Form>
<Item error={this.state.inputError}>
<Icon active name='ios-at-outline' />
<Input
autoCorrect={false}
placeholder='E-mail'
returnKeyType='go'
keyboardType='email-address'
autoCapitalize='none'
onChangeText = { (text) => updateEmail(text) }
/>
</Item>
<Text>{this.state.textError}</Text>
<Button full light style={{marginTop: 20}} onPress={ () => login }>
<Text>Login</Text>
</Button>
</Form>
</Content>
</Container>
);
};
export default UsersLoginView;
app/routes/users/login/index.js
import UsersLoginView from './view';
class UsersLogin extends Component {
constructor(props) {
super(props);
}
render() {
return (
<UsersLoginView />
);
}
}
export default UsersLogin;
maybe login function should be in index.js file then I will have access to state ?
The error is here: const UsersLoginView = (props) => {, you need to use a class if you want to maintain state.