Jessica Bulldog
Jessica Bulldog

Reputation: 158

Objects are not valid as a React child, recived data in console but not on display

I received dataAddress in the console with actual coordinates x, y. But I have a problem Objects are not valid as a React child (found: [object Promise]). I really don't understand what is wrong.

const BlogPage = () => {
  const data = useStaticQuery(graphql`
  query{
    allContentfulBlogPost{
      edges{
        node{
          location{lat, lon}
          }
        }
      }
    }
  `)
  const token = 'token';
  let getAddress = async (x, y) => {
    const api_url = await fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/${x},${y}.json?access_token=${token}`)
    const dataAddress = await api_url.json()
    console.log(dataAddress);
  }
  return (
    <Layout>

      {
        data.allContentfulBlogPost.edges.map((edge) => {
          return (
            <p>
              {
                getAddress(edge.node.location.lat, edge.node.location.lon)
              }
            </p>

          )
        })
      }
    </Layout>
  )
}

Upvotes: 0

Views: 146

Answers (1)

JayCodist
JayCodist

Reputation: 2544

A number of things are wrong in your code. Firstly, you should put the API call in a useEffect hook so it doesn't get called upon every render. Secondly, the function getAddress() returns a Promise object as it is marked as async. So you can't pass that in as a React child without at least adding the await keyword. Also you should have getAddress() function return the data of interest (probably the value of dataAddress) so you can use that value outside the function (right now, the function doesn't return anything). Or even better, set that value to your React state.

You could try:

...
const [address, setAddress] = React.useState({});

React.useEffect(() => {
  getAddress(edge.node.location.lat, edge.node.location.lon);
}, [])
...

And in the getAddress() function, set your returned value as part of your state:

let getAddress = async (x, y) => {
    const api_url = await fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/${x},${y}.json?access_token=${token}`)
    const dataAddress = await api_url.json()
    console.log(dataAddress);
    setAddress(dataAddress);
}

And in your JSX, just use the state value

...
<Layout>
    {data.allContentfulBlogPost.edges.map((edge) => {
        return (
            <p>{address}</p>
        )
    })}
</Layout>
...

Of course, this assumes the value of address isn't an object. If it is you'd have to use only primitive properties of that object in your JSX. For example, if it's an object with properties: x and y, your JSX could look like

...
<p>({address.x}, {address.y})</p>
...

Upvotes: 3

Related Questions