0

Preface: I'm fairly new to React (Coming over from Angular). I know things a similar but different. I have referenced the following SO threads to no avail in my situation: React not displaying data after successful fetch

Objects are not valid as a React child. If you meant to render a collection of children, use an array instead

Currently, I'm trying to get my data to display from an API I developed. I'm used to the Angular approach which would call for a ngFor in the template for most data showcase situations.

I'm having trouble wrapping my mind around what I have to do here in order to display my data. The data is expected to be an array of objects which I would then parse to display.

I also receive the following error: Error: Objects are not valid as a React child (found: object with keys {data}). If you meant to render a collection of children, use an array instead.

I've searched high and low for a solution but sadly, nothing I've seen has worked for me. (All of the answers on SO are using the class-based version of React, of which I am not).

You can see my data output in the following screenshot:

Drone Data From API

I am also including my custom hook code and the component that is supposed to render the data:

CUSTOM DATA FETCH HOOK


interface Drone{
    id: number;
    name: string;
    model: string;
    price: number;
}

export function useGetData(urlpath:string) {
    const [droneData, setData] = useState<any>()

    
    async function handleDataFetch(path:string){
        const result = await fetch(`https://drone-collections-api-jc.herokuapp.com${path}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'x-access-token': 'Bearer API-TOKEN'
            }
        })

        const response = await result.json();
        setData(response)
    }

    useEffect( () => {
        handleDataFetch(urlpath)
    })

    return droneData
}

THE DRONE COMPONENT

import { useGetData } from '../../custom-hooks'


export const Drones = () => {

    let data = useGetData('/drones')
    console.log(data)

    

    // const DisplayDrone = ( ) => {
    //     return (
    //         Array.prototype.map( data => {
    //         <div>{ data.name }</div>
    //         })
    //     )
    // }
    


    return ( 
        <div>
            <h1>Hello Drones</h1>
        </div>
    )
}

Also, for more context, the current code can be found at this repo: https://github.com/carter3689/testing-drone-frontend

Please, help me understand what I'm missing. Many Thanks!

Joel Carter
  • 151
  • 12

1 Answers1

2

There are several locations that needed to be fixed

In fetchData.tsx

export function useGetData(urlpath: string) {
  const [droneData, setData] = useState<any>([]);

  async function handleDataFetch(path: string) {
    const result = await fetch(`https://jsonplaceholder.typicode.com/posts`, {
      ...
    });
    const response = await result.json();
    setData(response);
  }

  useEffect(() => {
    handleDataFetch(urlpath);
  }, []);

Explanation:

  1. you need a "blank" array for looping through. I guess that the error causes by the fact that at the start, before the data is fetched, there is nothing to loop through. It's same as doing undefined.map(), which is obviously fail.
  2. You need a dependencies array for useEffect. Right now your code will do an infinite loop since everytime it get data, it update the state, thus re-run the useEffect and repeat. Add dependencies array limit when that useEffect will run

In Drones.tsx

return (
  <div>
    {data.map(item => <div>{item.name}</div>}
  </div>
)

Not much to say here. I don't use Angular so I'm not sure why you use Array.prototype.map, but in React you can loop through your variable directly. I also have a CodeSandbox link for your project (I use public API)

kunquan
  • 1,127
  • 1
  • 10
  • 24