1

I am trying to make an API call to grab some JSON data and display it in my React Native app, but it won't display the data to the actual app. I know that the call can work, because I am successfully calling it and logging it to the console, and I see the log - I just can't get it to display in the ReactNative portion of my code.

I think it may have to do with the fact that the JSON data has an array in it, and I'm not sure how to parse it. This is what my JSON looks like:

{"resultCode":0,"message":"[{\"id\":0000000,\"entityType\":\"NONE\",,\"namePrefix\":\"\",\"nameFirst\":\"\",\"nameMiddle\":\"\",\"nameLast\":\Doe\",\"nameSuffix\":\"\",\"address1\":\"1234 TEST ST\",\"address2\":\"\",\"city\":\"CUPERTINO\",\"state\":\"CA\",\"zip\":\"11111\",\"country\":\"US\",\"physicalAddress1\":\"1234 TEST ST\",\"phoneNumbers\":[],\"addresses\":[],\"email1\":\"[email protected]\",\"gender\":\"EMPTY\",\"dob\":\"Oct 24, 2016, 12:00:00 AM\",\"occupation\":\"\",\"createdTimestamp\":\"Aug 26, 2019, 9:55:24 PM\",\"modifiedTimestamp\":\"Aug 26, 2019, 9:55:24 PM\"}]"}

Basically there are two fields resultcode and message, but inside message is an array of more JSON data. I know it's ugly, but it's just a test and it's what I have to work with.

My React Native code is as follows:

import React, { Component } from 'react';
import { Text, View, FlatList, StyleSheet } from 'react-native';

export default class App extends React.Component {
    constructor( props: {} ) {
    super(props);

     this.state = {
         isLoading: true,
         dataSource: []
     };
 }

 componentDidMount() {
     fetch("https://mytestapi.com/test.json")
     .then((response) => response.json())
     .then((responseJson) => {
         this.setState({
             isLoading: false,
             dataSource: responseJson
         });
     });
 }

 renderItem = ({item, index}) => {
     let { resultCode, message } = item;

     if (!message[0]) return null;
     let details = message[0];

     return (
         <View style={styles.container}>
             <Text style={styles.header}>Entity ID: {details.entityId}</Text>
         </View>
     );
 }

 keyExtractor = (item, index) => {
     return index.toString();
 }

 render() {
     return (
         <View style={{flex: 1}}>
             <FlatList
                 data={this.state.dataSource}
                 keyExtractor={this.keyExtractor}
                 renderItem={this.renderItem}
             />
         </View>
     );
 }
}

const style = StyleSheet.create({
  container: {
      paddingTop: 45,
      backgroundColor: '#F5FCFF',
  },
  header: {
      fontSize: 25,
      textAlign: 'center',
      margin: 10,
     fontWeight: 'bold'
  },
});

const fetchAndLog = async() => {
   const response = await fetch("https://my.testapi.com/test.json");
   const json     = await response.json();
   console.log(json);
}

fetchAndLog();

I know that the call is successful, because the fetchAndLog function successfully logs to the console, so I'm just having an issue with displaying the JSON data in my React Native portion of the code. I've tried changing my code a few times, but can't seem to get it to print out the message portion of the JSON, and I've used this answer and this answer to try and help.

Any tips?

EDIT: Here's the error I get when trying to view it in the app:

Invariant Violation: Tried to get frame for out of range index NaN

This error is located at:
  in VirtualizedList (at FlatList.js:632)
  in FlatList (at App.js:45)
  in RCTView (at View.js:45)
  in View (at App.js:44)
  in App (at withExpoRoot.js:20)
  in RootErrorBoundary (at withExpoRoot.js:19)
  in ExpoRootComponent (at renderAPplication.js:35)
  in RCTView (at View.js:45)
  in View (at AppContainer.js:98)
  in RCTView (at View.js:45)
  in View (at AppContainer.js:115)
  in AppContainer (at renderApplication.js:34)
3
  • 2
    try simplifying your render function and just show the resultCode. Also, I'm concerned that this bit of code is messing the whole thing up: if (!message[0]) return null; Commented Nov 13, 2019 at 16:39
  • What I mean by the above comment is, I'm not sure you should ever return null. Try returning a component there instead. Commented Nov 13, 2019 at 16:43
  • 2
    Returning null is valid in React for a component Commented Nov 13, 2019 at 16:58

2 Answers 2

2

Looks like you're passing in an object as the FlatList data source, but you should be passing an array.

Try:

<FlatList
     data={this.state.dataSource.message}
     keyExtractor={this.keyExtractor}
     renderItem={this.renderItem}
/>

...

renderItem = ({item, index}) => {

     return (
         <View style={styles.container}>
             <Text style={styles.header}>Entity ID: {item.id}</Text>
         </View>
     );
 }

If you're not intending on showing an array of data, you should be using something besides FlatList. Also, I didn't see a field called entityId anywhere in that data.

Sign up to request clarification or add additional context in comments.

11 Comments

The only reason I made it a FlatList was because of the way I had an array in the JSON - could I just change the FlatList to a Text?
If all you want to display is a single field (not an array), then sure, a Text is all you need.
Hmm, your fix is getting my further, it doesn't give me an error anymore, but nothing displays on the screen...can I just move my return statement from renderItem up into the render function?
yes but the code would be something like <Text>Entity Id:{this.state.dataSource.message.id}</Text>
Scratch this I got it to work! Thanks so much! I was getting the above error because I had /* */ comments in my render function, which you can't have. But your solution worked!
|
1

Is the message always present? And is the data present when coming back? I would add a couple more checks:

 componentDidMount() {
   fetch("https://mytestapi.com/test.json")
   .then((response) => response.json())
   .then((responseJson) => {
     this.setState({
         isLoading: false,
         dataSource: responseJson || []
     });
  });
}

renderItem = ({item, index}) => {
     let { resultCode, message } = item;

     if (message == null || !message[0]) return null;
     let details = message[0];

     return (
         <View style={styles.container}>
             <Text style={styles.header}>Entity ID: {details.entityId}</Text>
         </View>
     );
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.