I'm new to react-native and I'm trying to build an application connected to a ruby on rails backend.
I have an index view in which I retrieve a list of lunches, I would like that when I click on one of them, I go to that presentation. so I created a specific view in which I redo an api call to retrieve the lunch data and then I display this one.
The problem is that it tries to read the data first and then it makes the api call after that while the method is in a componentWillMount() and the api call is done after that because I see it in the logs.
INDEX.js
import React from 'react';
import { View, Text, Image, StyleSheet, ScrollView, TouchableHighlight } from 'react-native'
import { Card, ListItem, Button } from 'react-native-elements'
import { Actions } from 'react-native-router-flux';
export default class IndexLunches extends React.Component {
constructor(props) {
super(props);
this.state = {
lunches: []
};
this.show = this.show.bind(this)
}
fetchLunches() {
fetch('http://192.168.1.24:3000/api/v1/lunches', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => {
if (response.ok) {
console.log('RESPONSE OK : GET LUNCHES')
var lunches = JSON.parse(response._bodyText);
var headers = response.headers
console.log(lunches)
console.log(headers)
this.setState({lunches: lunches})
} else {
alert("Erreur pendant la réceptions des lunchs voir les logs")
console.log(response)
}
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
// ADD THIS THROW error
throw error;
})
.done();
}
show(id) {
Actions.show_lunch({lunch_id: id})
}
lunchCard() {
lunches = this.state.lunches
return lunches.map((lunch, i) => {
return(
<TouchableHighlight key={i} onPress={() => this.show(lunch.id)}>
<View
// key={i}
// Error here because react auto execute onPress on load
>
<Image
style={{flex: 1, height: 150}}
source={{ uri: lunch.photos[0].url }}
/>
<Text>Titre du lunch : {lunch.title}</Text>
<View>
<Text>id : {lunch.id}</Text>
</View>
</View>
</TouchableHighlight>
);
});
}
// Its called before render component
componentWillMount() {
this.fetchLunches();
}
render () {
return (
<ScrollView>
<Text style={styles.title} > Liste des lunchs </Text>
<View>
{ this.lunchCard() }
</View>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
title: {
color: "#0000FF",
fontSize: 16,
marginBottom: 20,
},
text: {
}
})
Show.js
import React from 'react';
import { View, Text, Image, StyleSheet, ScrollView } from 'react-native'
import { Card, ListItem, Button } from 'react-native-elements'
export default class ShowLunch extends React.Component {
constructor(props) {
super(props);
this.state = {
lunch: {},
lunch_id: this.props.navigation.state.params.lunch_id
};
}
fetchLunch() {
let id = this.state.lunch_id
fetch(`http://192.168.1.24:3000/api/v1/lunches/${id}`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
})
.then((response) => {
if (response.ok) {
console.log(`RESPONSE OK : GET LUNCH, ID: ${id}` )
var lunch = JSON.parse(response._bodyText);
var headers = response.headers
console.log(lunch.lunch)
console.log(headers)
this.setState({lunch: lunch.lunch})
} else {
alert("Erreur pendant la réceptions du lunch voir les logs")
console.log(response)
}
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
// ADD THIS THROW error
throw error;
})
.done();
}
lunchView() {
lunch = this.state.lunch
console.log("ENTER IN LUNCH VIEW")
console.log(lunch)
return(
<View key="lunch">
<Image
style={{flex: 1, height: 150}}
source={{ uri: lunch.photos[0].url }}
/>
<Text>Titre du lunch : {lunch.title}</Text>
<View>
<Text>id : {lunch.id}</Text>
</View>
</View>
);
}
// Called before render component
componentWillMount() {
this.fetchLunch();
}
render () {
return (
<ScrollView>
<Text style={styles.title} >Lunch : </Text>
<View>
{ this.lunchView() }
</View>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
title: {
color: "#0000FF",
fontSize: 16,
marginBottom: 20,
},
text: {
}
})
Console.log
LOGIN SUCCESSFULL
Login.js:62 VALIDATE TOKEN SUCCESSFULL
Login.js:63 Response {type: "default", status: 200, ok: true, statusText: undefined, headers: Headers, …}
Login.js:65 {…}
IndexLunches.js:24 RESPONSE OK : GET LUNCHES
IndexLunches.js:27 (6) [{…}, {…}, {…}, {…}, {…}, {…}]
IndexLunches.js:28 Headers {map: {…}}
ShowLunch.js:48 ENTER IN LUNCH VIEW
ShowLunch.js:49 {}
ExceptionsManager.js:65 TypeError: Cannot read property '0' of undefined
This error is located at:
in ShowLunch (at navigationStore.js:319)
in Wrapped (at SceneView.js:31)
in SceneView (at CardStack.js:412)
in RCTView (at View.js:113)
in View (at CardStack.js:411)
in RCTView (at View.js:113)
in View (at CardStack.js:410)
in RCTView (at View.js:113)
in View (at createAnimatedComponent.js:134)
in AnimatedComponent (at Card.js:26)
in Card (at PointerEventsContainer.js:55)
in Container (at CardStack.js:454)
in RCTView (at View.js:113)
in View (at CardStack.js:383)
in RCTView (at View.js:113)
in View (at CardStack.js:382)
in CardStack (at CardStackTransitioner.js:97)
in RCTView (at View.js:113)
in View (at Transitioner.js:192)
in Transitioner (at CardStackTransitioner.js:49)
in CardStackTransitioner (at StackNavigator.js:60)
in Unknown (at createNavigator.js:52)
in Navigator (at createNavigationContainer.js:210)
in NavigationContainer (at Router.js:70)
in App (at Router.js:91)
in Router (at LunchRouter.js:31)
in LunchRouter (at App.js:16)
in RCTView (at View.js:113)
in View (at App.js:14)
in App (created by AwakeInDevApp)
in RCTView (at View.js:113)
in View (created by AwakeInDevApp)
in AwakeInDevApp (at registerRootComponent.js:34)
in RootErrorBoundary (at registerRootComponent.js:33)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:113)
in View (at AppContainer.js:102)
in RCTView (at View.js:113)
in View (at AppContainer.js:122)
in AppContainer (at renderApplication.js:34)
handleException @ ExceptionsManager.js:65
ReactNativeFiberErrorDialog @ ReactNativeFiber-dev.js:231
logCapturedError @ ReactNativeFiber-dev.js:19
captureError @ ReactNativeFiber-dev.js:2649
performWork @ ReactNativeFiber-dev.js:2601
batchedUpdates @ ReactNativeFiber-dev.js:2756
batchedUpdates @ ReactNativeFiber-dev.js:202
batchedUpdatesWithControlledComponents @ ReactNativeFiber-dev.js:209
_receiveRootNodeIDEvent @ ReactNativeFiber-dev.js:3559
receiveTouches @ ReactNativeFiber-dev.js:3572
__callFunction @ MessageQueue.js:302
(anonymous) @ MessageQueue.js:116
__guard @ MessageQueue.js:265
callFunctionReturnFlushedQueue @ MessageQueue.js:115
(anonymous) @ debuggerWorker.js:72
ExceptionsManager.js:73 TypeError: TypeError: Cannot read property '0' of undefined
This error is located at:
in ShowLunch (at navigationStore.js:319)
in Wrapped (at SceneView.js:31)
in SceneView (at CardStack.js:412)
in RCTView (at View.js:113)
in View (at CardStack.js:411)
in RCTView (at View.js:113)
in View (at CardStack.js:410)
in RCTView (at View.js:113)
in View (at createAnimatedComponent.js:134)
in AnimatedComponent (at Card.js:26)
in Card (at PointerEventsContainer.js:55)
in Container (at CardStack.js:454)
in RCTView (at View.js:113)
in View (at CardStack.js:383)
in RCTView (at View.js:113)
in View (at CardStack.js:382)
in CardStack (at CardStackTransitioner.js:97)
in RCTView (at View.js:113)
in View (at Transitioner.js:192)
in Transitioner (at CardStackTransitioner.js:49)
in CardStackTransitioner (at StackNavigator.js:60)
in Unknown (at createNavigator.js:52)
in Navigator (at createNavigationContainer.js:210)
in NavigationContainer (at Router.js:70)
in App (at Router.js:91)
in Router (at LunchRouter.js:31)
in LunchRouter (at App.js:16)
in RCTView (at View.js:113)
in View (at App.js:14)
in App (created by AwakeInDevApp)
in RCTView (at View.js:113)
in View (created by AwakeInDevApp)
in AwakeInDevApp (at registerRootComponent.js:34)
in RootErrorBoundary (at registerRootComponent.js:33)
in ExpoRootComponent (at renderApplication.js:35)
in RCTView (at View.js:113)
in View (at AppContainer.js:102)
in RCTView (at View.js:113)
in View (at AppContainer.js:122)
in AppContainer (at renderApplication.js:34)
at ShowLunch.lunchView (ShowLunch.js:54)
at ShowLunch.proxiedMethod (createPrototypeProxy.js:44)
at ShowLunch.render (ShowLunch.js:72)
at ShowLunch.proxiedMethod (createPrototypeProxy.js:44)
at finishClassComponent (ReactNativeFiber-dev.js:1667)
at updateClassComponent (ReactNativeFiber-dev.js:1659)
at beginWork (ReactNativeFiber-dev.js:1786)
at performUnitOfWork (ReactNativeFiber-dev.js:2528)
at workLoop (ReactNativeFiber-dev.js:2554)
at Object._invokeGuardedCallback (ReactNativeFiber-dev.js:73)
reactConsoleErrorHandler @ ExceptionsManager.js:73
console.error @ YellowBox.js:71
componentDidCatch @ RootErrorBoundary.js:71
proxiedMethod @ createPrototypeProxy.js:44
commitErrorHandling @ ReactNativeFiber-dev.js:2675
commitAllLifeCycles @ ReactNativeFiber-dev.js:2462
_invokeGuardedCallback @ ReactNativeFiber-dev.js:73
invokeGuardedCallback @ ReactNativeFiber-dev.js:47
commitAllWork @ ReactNativeFiber-dev.js:2485
workLoop @ ReactNativeFiber-dev.js:2555
performWorkCatchBlock @ ReactNativeFiber-dev.js:2587
_invokeGuardedCallback @ ReactNativeFiber-dev.js:73
invokeGuardedCallback @ ReactNativeFiber-dev.js:47
performWork @ ReactNativeFiber-dev.js:2604
batchedUpdates @ ReactNativeFiber-dev.js:2756
batchedUpdates @ ReactNativeFiber-dev.js:202
batchedUpdatesWithControlledComponents @ ReactNativeFiber-dev.js:209
_receiveRootNodeIDEvent @ ReactNativeFiber-dev.js:3559
receiveTouches @ ReactNativeFiber-dev.js:3572
__callFunction @ MessageQueue.js:302
(anonymous) @ MessageQueue.js:116
__guard @ MessageQueue.js:265
callFunctionReturnFlushedQueue @ MessageQueue.js:115
(anonymous) @ debuggerWorker.js:72
ShowLunch.js:24 RESPONSE OK : GET LUNCH, ID: 5
ShowLunch.js:27 {id: 5, title: "Coconut, Beef and Winter melon ", description: "["Propre subline nom origines sans vers.", "Italiq…rent mille qui.", "Pour nostalgique fin chemin."]", portion: 4, supply: "Aucun", …}
ShowLunch.js:28 Headers {map: {…}}
ExceptionsManager.js:73 Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.
Please check the code for the ShowLunch component.
I tried several things with the bind (this) or the arrows functions but I don't understand.