vasilis 123
vasilis 123

Reputation: 675

Unable to insert data to array in firebase firestore using react

This is my first time using firebase with react and I am trying to make an app where a user can insert songs in his private playlist in firebase firestore :

this is how I store a created user :

firebase.js

const app = firebase;
export const auth = app.auth();
export default app;

export const storage = firebase.storage();
export const db = firebase.firestore();
export const userCollection = db.collection('users');


export const CreateUser = async (email,password,username)=>{
  const authResult = await auth.createUserWithEmailAndPassword(email,password);
  userCollection.doc(authResult.user.uid)
    .set({
      created:firebase.firestore.FieldValue.serverTimestamp(),
      Email:email,
      userName:username,
      Playlist:[],
    });
} 
export const insertSong = async (song , email ) =>{
  await userCollection.where('Email' , '==' , email)
    .get()
    .then(snapshot=>{
      snapshot.forEach(snap=>{
        //if I console.log(snap.data()) my data is correct 
        snap.data().Playlist = [...snap.data().Playlist,song];
      })
    })
    .catch(err=>{
      console.log(err);
    })
}

where with the created user I set an empty playlist array as well

Now in another component, I try to update the playlist for the specific user

Upload.js

import {React , useState} from 'react';
import {insertSong, storage} from '../firebase';
import {useAuth} from './UserContext';

export default function Upload(){
  const {user} = useAuth(); //this is how I access the email of the user 
  const [disabled , setDisabled] = useState(false); 
  const [url , setUrl ] = useState(null);


  const checkSong = async (e)=>{ 
    const song = e.target.files[0];
    if(song){
      try{
        const songsRef = storage.ref('songs').child(song.name);
        setDisabled(true);
        await songsRef.put(song);
        console.log('Song has been inserted');
        const result = await songsRef.getDownloadURL();
        setUrl(result);  
        //if I do console.log(disabled) in this line it is false not true !
        insertSong(url,user.email); //this is where the problem happens 
      }catch(err){
        console.log(err);
      }
      setDisabled(false);
    } 
    
  }
  return (
    <div>
      <h1> Upload a song : </h1>
      <input type = "file" accept="audio/mp3,audio/*;capture=microphone" disabled = {disabled} onChange={checkSong}/>
    </div>
  );
  
}

so when I check the playlist of the user on the firebase website it is empty. I think there is a problem with the asynchronicity here as my disabled variable becomes false before I try to insert a song in the user's playlist as I have commented above. I would really appreciate your help here.

Upvotes: 1

Views: 717

Answers (2)

vasilis 123
vasilis 123

Reputation: 675

I created a new method to update the playlist array by getting the doc id as input and updating the document

const updateArray = async (id,song)=>{  
  const document =  userCollection.doc(id);
  await document.update({
    Playlist: firebase.firestore.FieldValue.arrayUnion(song)
  }).catch(err=>{
    console.log(err);
  })
        
}

export const insertSong = async (song , email ) =>{
  await userCollection.where('Email' , '==' , email)
    .get()
    .then(snapshot=>{
      snapshot.forEach(snap=>{
        updateArray(snap.id,song)
      })
    })
    .catch(err=>{
      console.log(err);
    })
}

The only problem is that if the playlist is empty it adds a null element at first and then works perfectly .

Upvotes: 0

p2hari
p2hari

Reputation: 558

inside insertsong try this

try{ 
var snapshot = await userCollection.where('Email' , '==' , email);

if(!snapshot.empty){
var docsnap = snapshot.docs[0];
    var playlist = docsnap.data().Playlist;
    //if I console.log(snap.data()) my data is correct 
         playlist = [...song];

   docsnap.ref.update({"Playlist": playlist});
  }
} 


catch { (err)=>{
  console.log(err);
}};

Upvotes: 1

Related Questions