2

I am trying to reach a nested array 4 objects deep, I have based my code off the example here: http://facebook.github.io/react-native/docs/tutorial.html#content

The error I get is:

undefined is not an object (evaluating 'Object.keys(dataBlob[sectionID])')

ListViewDataSource.js @ 206:0

cloneWithRowsAndSections ListViewDataSource.js @205:0

cloneWithRows ListViewDataSource.js @166:0

index.ios.js @ 40:0

This is a example of the json I have:

{
    "json": {
        "data": {
            "updated": {
                "$t": "04 Nov 2015 2321 GMT"
            },
            "flux": {
                "$t": "111"
            },
            "aindex": {
                "$t": "41"
            },
            "kindex": {
                "$t": "3"
            },
            "kindexnt": {
                "$t": "No Report"
            },
            "xray": {
                "$t": "B6.0"
            },
            "sunspots": {
                "$t": "95"
            },
            "heliumline": {
                "$t": "131.8"
            },
            "protonflux": {
                "$t": "3.14e-01"
            },
            "electonflux": {
                "$t": "5.46e+02"
            },
            "aurora": {
                "$t": "1"
            },
            "normalization": {
                "$t": "1.99"
            },
            "latdegree": {
                "$t": "67.5"
            },
            "solarwind": {
                "$t": "564.3"
            },
            "magneticfield": {
                "$t": "0.2"
            },
            "calculatedconditions": {
                "band": [
                    {
                        "name": "80m-40m",
                        "time": "day",
                        "$t": "Poor"
                    },
                    {
                        "name": "30m-20m",
                        "time": "day",
                        "$t": "Good"
                    },
                    {
                        "name": "17m-15m",
                        "time": "day",
                        "$t": "Fair"
                    },
                    {
                        "name": "12m-10m",
                        "time": "day",
                        "$t": "Poor"
                    },
                    {
                        "name": "80m-40m",
                        "time": "night",
                        "$t": "Fair"
                    },
                    {
                        "name": "30m-20m",
                        "time": "night",
                        "$t": "Good"
                    },
                    {
                        "name": "17m-15m",
                        "time": "night",
                        "$t": "Fair"
                    },
                    {
                        "name": "12m-10m",
                        "time": "night",
                        "$t": "Poor"
                    }
                ]
            }
        }
    }
}

Using the example I have the following in my index.ios.js:

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
} = React;


var API_URL = 'http://url.com/file.json';
var REQUEST_URL = API_URL;

var HFStatus = React.createClass({
  getInitialState: function() {
    return {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  },

  componentDidMount: function() {
    this.fetchData();
  },

  fetchData: function() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(responseData.datas),
          loaded: true,
        });
      })
      .done();
  },

  render: function() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderdata}
        style={styles.listView}
      />
    );
  },

  renderLoadingView: function() {
    return (
      <View style={styles.container}>
        <Text>
          Loading datas...
        </Text>
      </View>
    );
  },

  renderdata: function(data) {
    return (
      <View style={styles.container}>
          <Text style={styles.title}>{data.json.data.calculatedconditions.band.name}</Text>
          <Text style={styles.title}>{data.json.data.calculatedconditions.band.time}</Text>
          <Text style={styles.title}>{data.json.data.calculatedconditions.band.$t}</Text>
      </View>
    );
  },
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  rightContainer: {
    flex: 1,
  },
  title: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center',
  },
  year: {
    textAlign: 'center',
  },
  thumbnail: {
    width: 53,
    height: 81,
  },
  listView: {
    paddingTop: 20,
    backgroundColor: '#F5FCFF',
  },
});


AppRegistry.registerComponent('HFStatus', () => HFStatus);

2 Answers 2

5

It looks like you're trying to run clonewithrows on an object instead of an array. What you should do is this: (here is a working example with your data)

fetchData: function() {

  fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(responseData.json.data.calculatedconditions.band),
          loaded: true,
        });
      })
      .done();
  }

Then, in the renderdata function:

renderdata: function(data) {
    return (
      <View style={styles.container}>
          <Text style={styles.title}>{data.name}</Text>
          <Text style={styles.title}>{data.time}</Text>
          <Text style={styles.title}>{data.$t}</Text>
      </View>
    );
  },

https://rnplay.org/apps/D2soaw

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

3 Comments

Hello Nader Dabit, Nice answer but still i am confusion to get data from array inside array and render that data so can you please tell me in detail example ? i am new in this.
what is this (dataSource: this.state.dataSource.cloneWithRows) i have one API and i want to render that name into listview Please help.
And what is (componentDidMount) And what is (rowHasChanged: (row1, row2) => row1 !== row2,) this i will see this line in each example but i don't get to understand why we use ?
1

The ListView.DataSource.cloneWithRows method expects an array of data, and you appear to be passing it an object. Your sample data doesn't give away the exact format of your response, but by converting the API response into an array of items should solve the problem.

The confusing error message is caused by the fact that ListView.DataSource has another method, cloneWithRowsAndSections, that allows you to split your list view into sections with sticky section headers. This method in turn expects an object, where each key represents a section ID, and value is an array containing the row items belonging to that section.

It appears that when passing an object to cloneWithRows, React Native defaults to the cloneWithRowsAndSections behaviour, but because the object is not in a valid format, the rendering fails.

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.