WitchKing17
WitchKing17

Reputation: 184

Display JSON data via React Native - json array

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)

Upvotes: 1

Views: 2457

Answers (2)

Mike M
Mike M

Reputation: 4436

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.

Upvotes: 2

ageoff
ageoff

Reputation: 2828

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>
     );
 }

Upvotes: 1

Related Questions