DEV Community

Patrick Bradshaw
Patrick Bradshaw

Posted on

Firestore cross-reference returns a promise object, can't access document value [help]

I posted this on StackOverflow originally, but would welcome any suggestions:


My app is built with React and Firebase. There is a feature in the app that allows users to create playlists and fill them with tracks from a catalog. A Playlist has a sub-collection called "Tracks" that stores the track ID's and some other info. When viewing a playlist, I want to loop through the tracks and cross-reference them (like a join in SQL) to the Tracks collection to populate the view.

// Looks something like this before the return...

// Attempting to write an async/await function
async function getTrackDocument(trackId) {
  const track = await firestore
  return track;

useEffect(() => {
  const playlistRef = firestore.doc(`playlists/${playlistId}`);
  const playlistTracksRef = firestore.collection(

  playlistRef.get().then(doc => {
    if (doc.exists) {
      const unsubscribe = playlistTracksRef.onSnapshot(snapshot => {
        // Snapshot of playlist tracks
        const playlistTracks = => {
          return {
            // Getting the track document
            trackRef: getTrackDocument( => {


      return () => unsubscribe();
Enter fullscreen mode Exit fullscreen mode


The part where I am trying to cross-reference a Playlist Track ID to the Tracks collection:

trackRef: getTrackDocument( => {
Enter fullscreen mode Exit fullscreen mode

I was hoping that would give me the track information I needed. That part returns a promise object in the console:

trackRef: Promise
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Object
__proto__: Object
Enter fullscreen mode Exit fullscreen mode

And [[PromiseValue]] has all the values, but I can't get seem to get to where I can use the values. I can log to the console and it shows me the values I need eventually. Is there a way to return those values in-line the way the code is written? I've tried different ways of writing async/await functions, and I also tried to return a Promise.resolve(data), always the same results.

The closest I've come to the behavior I was hoping for was by creating a function where I could grab the Track and just push it to tracks array in state, like:

// @param arrayOfTrackIDs -- just track IDs from the playlist
function getTracksThenPopulateArray(arrayOfTrackIDs) {
   arrayOfTrackIDs.forEach(trackID => {
      firestoreTracks.doc(trackID).get().then(doc => setTracks(tracks => [...tracks, track])); 
Enter fullscreen mode Exit fullscreen mode

This wasn't ideal however because I couldn't incorporate .onSnapshot() to update the view if tracks were removed or added.

Discussion (0)