skip to Main Content

I have an API called getQuote and a component called QuoteCard. Inside QuoteCard I’m trying to render an array of users that liked a quote. The API works fine, I have tested it, and the code below for getting the users works fine too.

const Post = async (url, body) => {
  let res = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "accept": "*/*"
    },
    body: JSON.stringify(body)
  }).then(r => r.json());
  return res;
}

const getAllLikes = async () => {
    let users = await Post('api/getQuote', {
      id: "639e3aff914d4c4f65418a1b"
    })

    return users
  }

  console.log(getAllLikes())

The result is working as expected :

enter image description here

However, when trying to map this promise result array to render it onto the page is where I have problems. I try to render like this:

<div>
{getAllLikes().map((user) => (
    <p>{user}</p>
))}
</div>

However, I get an error that states:

getAllLikes(…).map is not a function

I don’t understand why this is happening. Why can’t I map the array? Is it because it’s a promise or something?

And if anyone needs to see the getQuote API, here it is:

//Look ma I wrote an API by myself! :D

import clientPromise from "../../lib/mongodb";
const ObjectId = require('mongodb').ObjectId;
import nc from "next-connect";

const app = nc()

app.post(async function getQuote(req, res) {
  const client = await clientPromise;
  const db = client.db("the-quotes-place");
  
  try {
    let quote = await db.collection('quotes').findOne({
      _id: new ObjectId(req.body.id)
    })

    res.status(200).json(JSON.parse(JSON.stringify(quote.likes.by)));
  } catch (e) {
    res.status(500).json({
      message: "Error getting quote",
      success: false
    })
    console.error(e);  
  }
})

export default app

Thanks for any help!

2

Answers


  1. I am from Angular and I believe we call pipe on Observables (or Promises). Map can then be called inside the pipe function

    observable$ = getAllLikes().pipe(map( user => <p>{user}</p>))
    

    If there is no pipe, I can only think of manually subscribing (which is not a good practice)

    sub$ = getAllLikes().subscribe( user => <p>{user}</p>)
    

    // unsub from sub$ appropriately
    // We do this from ngOnDestroy in angular

    ngOnDestroy() {
       this.sub$?.unsubscribe()
    }
    
    Login or Signup to reply.
  2. It is due to the fact that getAllLikes is an async function and thus it returns promise which does not have a map function.

    You can either save it in a state variable before using await Or chain it with .then.

    Minimal reproducible example which works

    const getAllLikes = async () => {
        return ['a', 'b']
    }
    getAllLikes().then((r) => r.map((g) => { console.log(g) }))
    

    Edit: The above code won’t work if directly used with jsx since the return of getAllLikes will still be a promise. Solution would be to save it in a state variable and then using it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search