0

I'm trying to use an array returned from Node in a React code.

Here's the Node's router code:

router.get('/prodlist', async (req, res) => {
  try {
    await Product.find({}).exec((err, result) => {
      res.status(200).send({ express: result })
    })
  } catch (e) {
    console.log(e)
    res.status(400).send(e)
  }
})

The React's component code:

import React, { useState, useEffect } from 'react';

function App() {
  const [datas, setDatas] = useState(null)

  useEffect(() => {
    var curURL = window.location.href
    var calledRoute = curURL.substr(8).substr(curURL.substr(8).indexOf("/"))
    callBackendAPI(calledRoute)
      .then(res => setDatas(prevData => res.express))
      .catch(err => console.log(err));
  }, [])

  async function callBackendAPI(routePath) {
    const response = await fetch(routePath);
    const body = await response.json();

    if (response.status !== 200) {
      throw Error(body.message)
    }
    console.log(body.express)
    return body;
  }

  return (
    <div className="App">
      {{datas}}
    </div>
  )
}

export default App;

And the array content (seen from Chrome's developer tools):

(3) [{…}, {…}, {…}]
  0:
    prodDesc: "Prod1"
    prodID: "1"
    prodImage: "prod1.jpg"
    prodPrice: 350
    prodRebate: 100
    prodReviews: []
    prodStock: 31
    prodThumb: "prod1.jpg"
    __v: 0
    _id: "5eb04a6439eec26af4981541"
    __proto__: Object
  1: {prodID: "2", prodDesc: "Prod2", prodThumb: "prod2.jpg", prodImage: "prod2.jpg", prodPrice: 1500.79, …}
  2: {prodID: "3", prodDesc: "Prod3", prodThumb: "prod3.jpg", prodImage: "prod3.jpg", prodPrice: 280.79, …}
  length: 3
  __proto__: Array(0)

When I execute this code I get the error: Objects are not valid as a React child

So I tried to map data's content with a line like this:

{datas.map((item) => <p>{item}</p>)}

Executing this code with a map I get the error : Cannot read property 'map' of null.

Although datas contains an array, it seems React sees it as null.

Anybody understands this issue?

EDIT: I didn't realized that this question is about two different issues. Norbitrial's answer fixed the problem about synchronicity but I still get the error "Objects are not valid as a React child [...] use an array instead".

EDIT2: Solved the issue by forwarding the mapping to a REACT component with the following line:

{datas && datas.map(item => <ShopCart key={item.prodID} item={item} />)}
2

3 Answers 3

2

The problem is your backend API returns the result asynchronously so it might take few seconds while your state value is null.

The solution can be checking for null value first then using the .map() on your state called datas with && in your code.

Try as the following:

{datas && datas.map((item) => <p>{item}</p>)}

I hope this helps!

Sign up to request clarification or add additional context in comments.

Comments

0

The code runs before datas is populated from your api, you need to first check to make sure it is populated like this.

{datas && datas.length && datas.map((item) => <p>{item}</p>)}

Comments

0

The problem is that your component gets mounted before you receive the data.

What I would do(and most people) is to create a loading component that will show a spinner or something like that when the array is empty and after it gets filled it should render the component with the data.

But a quick solution to this is to do a conditional render


{datas.length && datas.map((item) => <p>{item}</p>)}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.