The Condor
The Condor

Reputation: 1054

Displaying data from Firebase in React without arrays

I am new to both React and Firebase. I struggled a bit to get data from the database, even though the instructions on the Firebase website were pretty straightforward.

I managed to print data in the view by using this code:

Get data from DB and save it in state:

INSTRUMENTS_DB.once('value').then(function(snapshot) {
        this.state.instruments.push(snapshot.val());
        this.setState({
            instruments: this.state.instruments
        });

From Firebase, I receive and Object containing several objects, which correspond to the differen instruments, like shown in the following snippet:

Object {
    Object {
        name: "Electric guitar",
        image: "img/guitar.svg"
    }
    Object {
        name: "Bass guitar",
        image: "img/bass.svg"
    }
    // and so on..
}

Currently, I print data by populating an array like this:

var rows = [];
    for (var obj in this.state.instruments[0]) {
        rows.push(<Instrument name={this.state.instruments[0][obj].name}
                              image={this.state.instruments[0][obj].image}/>);
    }

I feel like there's a better way to do it, can somedody give a hint? Thanks

Upvotes: 1

Views: 2039

Answers (3)

Chris Panayotoff
Chris Panayotoff

Reputation: 1956

I user firebase a lot and mu solution is little ES6 helper function

const toArray = function (firebaseObj) {

return Object.keys(firebaseObj).map((key)=> {
    return Object.assign(firebaseObj[key], {key});
})

};

I also assign the firebase key to object key property, so later I can work with the keys.

Upvotes: 2

Pineda
Pineda

Reputation: 7593

The native map function only works for arrays, so using directly it on this object won't work.

What you can do instead is:

Call the map function on the keys of your object using Object.keys():

getInstrumentRows() {
  const instruments = this.state.instruments;
  Object.keys(instruments).map((key, index) => {
    let instrument = instruments[key];
    // You can now use instrument.name and instrument.image
    return  <Instrument name={instrument.name} image={instrument.image}/>
  });
}


Alternatively, you can also import the lodash library and use its map method which would allow you to refactor the above code into:

getInstrumentRowsUsingLodash() {
  const instruments = this.state.instruments;
    _.map(instruments, (key, index) => {
    let instrument = instruments[key];
    // You can now use instrument.name and instrument.image
    return  <Instrument name={instrument.name} image={instrument.image}/>
  });
}

Side note: When you retrieve you data from Firebase you attempt to update the state directly with a call on this.state.instruments. The state in React should be treated as Immutable and should not be mutated with direct calls to it like push.

Upvotes: 1

Piotr Sołtysiak
Piotr Sołtysiak

Reputation: 1006

I would use map function:

_getInstrumentRows() {
    const instruments = this.state.instruments[0];
    if (instruments) {
        return instruments.map((instrument) => 
            <Instrument name={instrument.name}
                        image={instrument.image}/>);
    }
}

In your render() method you just use {_getInstrumentRows()} wherever you need it.

Upvotes: 0

Related Questions