corasan
corasan

Reputation: 2754

React Native - ListView not rendering data from Firebase

I'm trying to use React Native ListView component but it's not rendering. ListView takes a dataBlob which is an array and thats what I'm passing to it.

In my main component I use componentWillMount to get the data from Firebase. This gives me an array of objects containing the message and sender.

Example: [{text: 'Hello', sender: 'p1'}, {text: 'Hi', sender: 'p2}]

Main Component:

constructor(props) {
    super(props);
    this.state = {
        messages: []
    }
}

componentWillMount() {
    app.database().ref('messages/').on('child_added', function(snapshot) {
        let data = snapshot.val();
        for(let i in data) {
            this.state.messages.push(data[i]);
        }
        this.setState({messages: this.state.messages});
    }.bind(this));
}

render() {
    return (
        <View>
            <MessagesList messages={this.state.messages}/>
        </View>
    )
}

MessagesList Component:

constructor(props) {
    super(props);
    const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2 });
    this.state = {
        dataSource: ds.cloneWithRows(props.messages)
    }
}
renderRows = (data) => {
    return (
        <View>
            <Text>{data.text}</Text>
        </View>
    )
}

render() {
    return(
        <ListView
            dataSource={this.state.dataSource}
            renderRow={(data) => this.renderRows(data)}
            enableEmptySections={true}
        />
    )
}

When I hard code an array of objects into the dataSource it works but doesn't work with the array pass from the main component.

Upvotes: 1

Views: 1133

Answers (1)

Ivan Chernykh
Ivan Chernykh

Reputation: 42166

Change your MessagesList component' constructor like:

 constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
          rowHasChanged: (row1, row2) => row1 !== row2,
        })
    };
 }

Then add this utility function:

 getDataSource(messages: Array<any>): ListView.DataSource {
    if(!messages) return;
    return this.state.dataSource.cloneWithRows(messages);
 }

Also add this:

 componentDidMount(){
    this.setState({dataSource: this.getDataSource(this.props.messages)});
 }

And then these lines should do the trick:

 componentWillReceiveProps(props) {
    this.setState({dataSource: this.getDataSource(props.messages)});
 }

Sorry, didn't have a time to test it, but i hope you will get the idea!

Upvotes: 2

Related Questions