Lullaby
Lullaby

Reputation: 119

Getting a specific object/item by id in Firebase

I am currently building a small web app with Firebase and React, but I am having trouble fetching for specific items in the Firebase from the React client-side.

That being said, I'm used to javascript, where a simple fetch might look something like:

const url = 'www.example.com/api/'
const id = '123'
fetch(url + id) <---specific
  .then(res => res.json())
  .then(result => this.setState({results: result})
  .catch(err => console.log(err))

However, I haven't been able to find any documentation on something that looks similar with firebase.

A more specific issue below:

class StoryItem extends Component {
   constructor(props) {
   super(props);
    this.state = {
      story: this.props.location.myCustomProps
    };
   }
 componentDidMount() {
   //this should do a fetch request based on the 
  //params id to get the specific item in the firebase
  //right now it is being passed as prop which is unreliable because when page refresh state is reset

  //user should be able to access content 
  //without having to go to previous page
console.log(this.state.story)
}

One way I've tried to get the specific object from the firebase is this:

 componentDidMount(props) {
   const ref = firebase.database().ref("items");
   ref.on("value", snapshot => {
    let storiesObj = snapshot.val();
     storiesObj
      .child(this.props.match.params.id)
      .then(() => ref.once("value"))
      .then(snapshot => snapshot.val())
      .catch(error => ({
         errorCode: error.code,
         errorMessage: error.message
       }));

     });
   }

In this case, the error is enter image description here

Any help would be appreciated, also, if anyone knows of any good documentation on firebase, feel free to send me a link.

Thank you

Upvotes: 1

Views: 7015

Answers (1)

Gleb Kostyunin
Gleb Kostyunin

Reputation: 3883

The trick is, you don't have to get the value of all items first, as you do. You should locate the items ref, then lookup a child that you want and get the value of that child with .on or .once.

Something like that, based on your example code:

componentDidMount() {
   firebase.database().ref("items");
      .child(this.props.match.params.id)
      .once("value")
      .then(snapshot => snapshot.val())
      .catch(error => ({
         errorCode: error.code,
         errorMessage: error.message
       }));
   }

For better understanding, let's take a look at the original code and try to figure out why it errors out:

componentDidMount(props) {
   // ⬇️ this ref points to ALL items
   const ref = firebase.database().ref("items");

   // ⬇️ here we're asking for the value stored under the above ref
   ref.on("value", snapshot => {
    let storiesObj = snapshot.val();
     /* so firebase gives us what we ask for, storiesObj
      * is probably a huge js object with all the items inside.
      * And since it's just a regular js object, 
      * it does not have a `child` method on it, thus calling .child errors out.
      */
     storiesObj
      .child(this.props.match.params.id)
      .then(() => ref.once("value"))
      .then(snapshot => snapshot.val())
      .catch(error => ({
         errorCode: error.code,
         errorMessage: error.message
       }));

     });
   }

Upvotes: 5

Related Questions