Fernando Maymone
Fernando Maymone

Reputation: 755

How to set only ONE element in an array in firebase

I have an array saved on my firebase, like this:

matches:[ {match:{id:1,data:...}}]

I want to save just one item on firebase at this array. For example, my match have id:32. I want to find it on the array saved in firebase, and change it.

Im trying to make this. But Im thinking that this is VERY UGLY to make a request to the firebase, copy the array, and save the entire array again.

const ref = `/users/${currentUser.uid}/matches`;
      var list = [];
       firebase.database().ref(ref).on('value',  function (snap) { list = snap.val(); });

  if (list.length > 0) {
    const indexToUpdate = list.findIndex(k => k.name == match.name)
    if (indexToUpdate >= 0) {
      list[indexToUpdate] = match;

      return dispatch => {

         firebase
          .database()
          .ref(`/users/${currentUser.uid}/matches`)
          .set(list)
          .then(() => {
            dispatch({ type: MATCH_UPDATE, payload: match });
          });

      };
    }
  }

Any light?

enter image description here

Upvotes: 2

Views: 1637

Answers (3)

Frank van Puffelen
Frank van Puffelen

Reputation: 599836

This line of code:

const indexToUpdate = list.findIndex(k => k.name == match.name)

Is a dead giveaway that your data structure is not ideal.

Consider storing the matches under their name, prefixing it with a string to prevent the array coercion that Kenneth mentioned. So:

matches
  match1
    date: "2018-06-14..."
    ...
  match2
    date: "2018-06-16..."
    ...

With this you can look up the node for a match without needing a query. It also prevents using an array, which is an anti-pattern in Firebase precisely because of the reason you mention.

For more on this, see the classic Firebase blog post on Best Practices: Arrays in Firebase.

Upvotes: 2

Stradosphere
Stradosphere

Reputation: 1285

You need to reference the ID of the item you are trying to set by ID in the URL

     firebase
      .database()
      .ref(`/users/${currentUser.uid}/matches/32`)
      .set(list)
      .then(() => {
        dispatch({ type: MATCH_UPDATE, payload: match });
      });

Also, use snap.key to get the ID you need if index isn't working.

Upvotes: 0

Kenneth Truong
Kenneth Truong

Reputation: 4176

Firebase stores arrays as object and converts it back to array when it comes back to the client if the keys are ordered numerically correctly

But basically it should be able to work the same where you make your path up to the object you want to update.

firebase
  .database()
  .ref(`/users/${currentUser.uid}/matches/${indexToUpdate}`)
  .set(match)
  .then(() => {
    dispatch({ type: MATCH_UPDATE, payload: match });
  });

Upvotes: 1

Related Questions