tinker
tinker

Reputation: 642

Firebase Key/Value access not working

I have the following data setup in firebase.

{ 
  "data": {
    "lava14mod1":"down",
    "lava14mod2":"up"
  }
}

I'm able to access it in my React app. But I can only access it as a (key,value) pair combined as one string.

I cannot access the key or value separately using,

<li>{this.state.data[0]['.key']}</li>

I'm getting this error,

Uncaught TypeError: Cannot read property '.key' of undefined

Uncaught TypeError: Cannot read property '_currentElement' of null

Here's the full code, running on plunker, (without the error line)

http://plnkr.co/edit/zjFKsYAzfYrzGmedVEV6?p=preview

I've been pouring through the docs and still can't figure this out. I'm following the data structure shown in firebase docs,

[
  {
    ".key": "-Jtjl482BaXBCI7brMT8",
    ".value": 100
  },
  {
    ".key": "-Jtjl6tmqjNeAnQvyD4l",
    "first": "Fred"
    "last": "Flintstone"
  },
  {
    ".key": "-JtjlAXoQ3VAoNiJcka9",
    ".value": "foo"
  }
]

Firebase documentation

Is there some problem with my syntax? How do I access the key or value separately? Thank you so much.

Upvotes: 0

Views: 892

Answers (1)

jered
jered

Reputation: 11571

You're getting that error because the this.state.data object does not have the keys you're trying to access in render.

This is easy to see if you simply put a console.log(this.state.data) in render. Doing so gives me something like this in the console:

> []
> [Object]
> [Object, Object]
> [Object, Object, Object]

So, render is being called four different times, once each time that this.state.data is being updated with a new key. But, in your render, you don't consider the fact that keys [0] and [1] might not exist - you try to access them without checking them first.

Now I'm not sure exactly why your state is being updated piecemeal, but it probably has something to do with the ReactFireMixin which I have no experience with. Fetching form Firebase is clearly an asynchronous action (since you have to grab data from the cloud) so you need to make accommodations for that.

The most straightforward fix is simply checking to make sure that the key you want to access actually exists on an object before you try to access it (which is a good practice in most cases to avoid exactly this kind of error!)

render: function() {
    return (
        <div>

          from firebase,
          {this.state.data ? <li>{this.state.data}</li> : undefined}
          {this.state.data && this.state.data[0] && this.state.data[0][".key"] ? <li>{this.state.data[0][".key"]}</li> : undefined}
          {this.state.data && this.state.data[1] && this.state.data[1][".key"] ? <li>{this.state.data[1][".key"]}</li> : undefined}

          local var,
          <li>{data2[0]['.key']}</li>


        </div>
    );
}

http://plnkr.co/edit/7XXaOIQCQcyGneqEqa88?p=preview

An even better solution would be to use Array.map to convert whatever array this.state.data is at the time directly into some kind of list. This is a very common pattern in React applications because you'll often keep lists of data as arrays and then want to display it dynamically.

render: function() {
    return (
        <div>

          from firebase,
          {this.state.data.map(function(ea){return <li>Key: <strong>{ea[".key"]}</strong>, Value: <strong>{ea[".value"]}</strong></li>})}

          local var,
          <li>{data2[0]['.key']}</li>


        </div>
    );
}

http://plnkr.co/edit/b1j10M1i635hvapFxZbG?p=preview

More about Array.map()

Upvotes: 1

Related Questions