score:0

There are a few conceptual misunderstandings that I want to tackle in your code.

In modern React, your components should typically render some type of jsx, which is how React renders html. In your first example, you are using App to return your genres to your Screen component, which you don't need to do.

If your goal is to fetch some genres and then ultimately print them out onto the screen, you only need one component. Inside that component, you will useEffect to call an asynchronous function that will then await the api data and set it to a react state. That state will then be what you can iterate through.

When genres is first rendered by react on line 6, it will be undefined. Then, once the api data is retrieved, React will update the value of genre to be your array of genres which will cause the component to be re-rendered.

{genres && genres.map((genre) ... on line 20 checks to see if genres is defined, and only if it is, will it map (like looping) through the genres. At first, since genres is undefined, nothing will print and no errors will be thrown. After the genres are set in our useEffect hook, genres will now be an array and we can therefore loop through them.

Here is a working example of your code.

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

import { getGenres } from "./api/functions";

function App() {
  const [genres, setGenres] = useState();

  useEffect(() => {
    async function apiCall() {
      const apiResponse = await getGenres("tv");
      console.log(apiResponse);
      setGenres(apiResponse);
    }
    apiCall();
  }, []);

  return (
    <div>
      <h1 className="text-3xl font-bold underline">H1</h1>
      {genres && genres.map((genre) => <div key={genre}>{genre}</div>)}
    </div>
  );
}

export default App;

score:0

You should use a combination or useEffect and useState

You should use useEffect to launch the async get, without launching it each rerendering. If a async function is used to get some data from outside the component, this is called 'side effect' so use useEffect.

You should use useState to react to changes on theses side effects, re-rendering the component to get the data in the dom.

In the next example, Im using a dummy async function getGenres which returns an array of genres.

Here is an example and a WORKING EXAMPLE :

const {useState, useEffect} = React;


async function getGenres() {

    var promise = new Promise(function(resolve, reject) {
     window.setTimeout(function() {
       resolve( ['genre1', 'genre2']);
     });
   });
   return promise;
   
}

const Screen = () => {
  const [genres, setGenres] = useState([])

  useEffect(
     () => {
        getGenres().then(
        res => setGenres(res)
      )
    }, [getGenres]
  )
  
  
  return (
    <ul>
      {
      genres.map(
        i => <li>{i}</li>
      )
      }
    </ul>
  );
}


const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<Screen/>)

Related Query

More Query from same tag