1

I'm writing a comment system built with two databases: one contains the text and the ID of the commenter, which then is used to access the second database to retrieve & dynamically display the poster's profile information (pfp and display name) for each comment they've submitted.

The function inside the useEffect() hook returns an array of Promises. I've been trying to figure out ways to access values inside these Promises but so far to no avail. I know that .then() exists specifically for this purpose but I don't understand how and where to apply it properly in this case.

import React, { useEffect, useState, Fragment } from 'react'
import firebase from './firebase'

export const Comments = () => {

    const [cred, setCred] = useState('')
    const [comment, setComment] = useState('')
    const [allComments, setAllComments] = useState(null)

    useEffect(() => {

// grab the database containing poster ID 
// & text of each single comment by it's name and then map over it

        firebase.getData('text&ID').onSnapshot(snapshot => setAllComments([...snapshot.docs.map(async (doc) => {

// using the poster ID, 
// access the 'users' DB that contains the avatar & name fields

            let comment = doc.data().content
            let poster = await firebase.getData('users').doc(doc.data().posterID).get()
            let name = poster.data().name
            let avatar = poster.data().avatar

// returning an object of all the data we want to display for each comment

            return ({
                name: name,
                avatar: avatar,
                comment: comment
            })
        })]))

// if user exists, set state to their credentials

        firebase.isInitialized().then(val => setCred(val))       
    }, [])

    return allComments && <Fragment>

// submit the comment to the text&DB collection with text, poster ID and text 

        {cred && <form onSubmit={(e) => {
            e.preventDefault()
            firebase.addComment('text&ID', cred.uid, comment).then(console.log('comment sent!')).then(setComment(''))
        }}>
            <input
                type="text"
                value={comment}
                name="text"
                placeholder="comment..."
                onChange={e => { setComment(e.target.value) }}
                required
            />
            <br />
            <button >Post</button>
        </form>}
        <ul>

// the plan was to map over allComments 
// and return an <li> with all the display info
// but logging to console displays THE array of Promises
// that I want to access

            {console.log(allComments)}
        </ul>
    </Fragment>
}

Any and all input is highly welcome.

Here's the console.log output:

[Promise]
   0: Promise
      __proto__: Promise
         [[PromiseStatus]]: "resolved"
         [[PromiseValue]]: Object
            avatar: "https://i.imgur.com/v4ImnVE.jpg"
            comment: "no halo"
            name: "polnareff"
         __proto__: Object
      length: 1
      __proto__: Array(0)
  • Hi, not sure I'm going to explain this well. You are right, where your console.log is you will need to resolve the promise ".then()" and ".map" the result. I get this wrong waaay too many times myself. Please add to your post the console.log output and I will write up some code to help you resolve it. – Francois Nov 02 '19 at 11:51
  • @Francois edited in the contents of console.log output. Thanks for you reply! – tremendous snake Nov 02 '19 at 12:10
  • I suggest looking at promise.all() It basically takes in a array of promises. `Promise.all([Promise1, Promise2, Promise3]) .then(result) => { console.log(result) }) .catch(error => console.log(`Error in promises ${error}`))` it might be what you are looking for. – Francois Nov 02 '19 at 12:46
  • Here is a blog post that I found explaining it https://www.freecodecamp.org/news/promise-all-in-javascript-with-example-6c8c5aea3e32/ – Francois Nov 02 '19 at 12:47
  • If this gives you the correct output just replace the console.log with ` result.map(item => {
  • {item.comment}
  • })` etc. – Francois Nov 02 '19 at 12:50
  • Does this answer your question? [How to access the value of a promise?](https://stackoverflow.com/questions/29516390/how-to-access-the-value-of-a-promise) – Vahid Al Nov 02 '19 at 13:19
  • 1
    @Francois this worked, thanks a TON. At first i got the "Objects are not valid as a React child" error but all it took to fix was to simply reintegrate your solution into the useEffect() and now it's working like a clock. A million thanks! – tremendous snake Nov 02 '19 at 13:42
  • 1
    @VahidAl saw your comment only after I was already done, was a useful read still, thanks! – tremendous snake Nov 02 '19 at 13:44
  • Great! Happy to help. Please mark the answer as correct? – Francois Nov 02 '19 at 14:14