Kalyani Pullela
Kalyani Pullela

Reputation: 119

how to render a collection of children using array

I'm creating a grocery list application in which front-end is react-native and back-end is firebase.In the grocery list the items are to be added. I have stored some of the items in firebase and retrieving the same from the firestore but it shows an error:

Error

Objects are not valid as a React child(found:object with keys($$typof,key,ref,props,_owner,_store). If you meant to render a collection of children, use an array instead.

I'm using react-native 0.55.4 version. please help me out.

this is index.js file

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  ListView,TouchableHighlight,AppRegistry
} from 'react-native';
import * as firebase from 'firebase';
import ToolBar from './app/components/ToolBar/ToolBar';
const styles = require('./app/style');

const firebaseConfig = {
  apiKey: 'AIzaSyClhqB9TEEffc4szIHUEVt0OqXvKQOEwxQ',
    authDomain: 'grocerryapp-fbe06.firebaseapp.com',
    databaseURL: 'https://grocerryapp-fbe06.firebaseio.com',
    projectId: 'grocerryapp-fbe06',
    storageBucket: 'grocerryapp-fbe06.appspot.com',
    messagingSenderId: '903884995524'
}
const firebaseApp = firebase.initializeApp(firebaseConfig);


export default class App extends Component {
  constructor(){
    super();
    let ds= new ListView.DataSource({rowHasChanged:(r1,r2) => r1 !== r2});
    this.state={
      itemDataSource:ds
    }

    this.itemsRef = this.getRef().child('items');
    this.renderRow = this.renderRow.bind(this);
    this.pressRow = this.pressRow.bind(this);
  }
  getRef(){
    return firebaseApp.database().ref();
  }
  componentWillMount() {
    this.getItems(this.itemsRef);
  }
  componentDidMount() {
    this.getItems(this.itemsRef);
  }
  getItems(itemsRef) {
    //let items = [{title: 'Item One'},{title: 'Item Two'}];
    itemsRef.on('value',(snap) => {
      let items = [];
      snap.forEach((child) => {
        items.push({

          title: child.val().title,
          _key: child.key

        });
      });
      this.setState({
        itemDataSource: this.state.itemDataSource.cloneWithRows(items)
      });
    });
  }
  pressRow(item){
    console.log(item);
  }
renderRow(item){
  return(
    <TouchableHighlight onPress={() => {
      this.pressRow(item);
    }}>
<View style={styles.li}>
<Text style={styles.liText}>{item.title}</Text>
</View>
    </TouchableHighlight>
  );
}


  render() {
    return (
      <View style={styles.container}>
      <ToolBar title="Item Lister" />
      <ListView
        dataSource={this.state.itemDataSource}
        renderRow={this.renderRow}

      />
            </View>
    );
  }
}


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

Upvotes: 1

Views: 1274

Answers (3)

MoKhajavi75
MoKhajavi75

Reputation: 2712

I've seen this error and i guess it's related to firebase library! The current version is buggy so use the 5.0.2 version instead!

npm install --save [email protected]

Upvotes: 0

Gavin Thomas
Gavin Thomas

Reputation: 1867

I think this is an async issue. Your setState is firing before your forEach has finished and thus your this.state.itemDataSource.cloneWithRows(items), items is incomplete.

getItems(itemsRef) {
//let items = [{title: 'Item One'},{title: 'Item Two'}];
itemsRef.on('value',(snap) => {
  let items = [];
  snap.forEach((child) => {
    items.push({

      title: child.val().title,
      _key: child.key

    });
  });
  this.setState({
    itemDataSource: this.state.itemDataSource.cloneWithRows(items)
  });
});

}

You could...

getItems(itemsRef) {
//let items = [{title: 'Item One'},{title: 'Item Two'}];
itemsRef.on('value',(snap) => {
let items = [];
snap.forEach((child) => {
  items.push({

    title: child.val().title,
    _key: child.key

  });
});
}.then(() => {
  this.setState({
    itemDataSource: this.state.itemDataSource.cloneWithRows(items)
  })
})

});
}

Upvotes: 1

Pravin
Pravin

Reputation: 195

return() will help you

 render() {
  return (
    <View style={styles.container}>
    <ToolBar title="Item Lister" />
    <ListView
      dataSource={this.state.itemDataSource}
      renderRow={(rowData) => {
       return(
        <View>
          <TouchableHighlight 
          onPress={() => this.pressRow(rowData)}
          >
           <View style={styles.li}>
             <Text style={styles.liText}>{item.title}</Text>
           </View>
          </TouchableHighlight>
       </VIew>
       )
      }}
    />
    </View>
 );
 }

Upvotes: 0

Related Questions