How to use Map function in react js with Api

Hi l am new to react and started to learn something new. I am actually stuck in a situation where I know how the solution can be achieved but I do not know the implementation part.

I Am trying to use API using Await Async and show data in my card. I can see results on the console log but not in the card.

I think as far as I know, I have to use map function to map the data with my card to see all data. Please correct me if wrong.

Also if you can let me know what needs to be done next looking at my code and how will be great.

import React ,{useEffect, useState} from 'react';
import { Button, Card, CardActionArea, CardActions, CardContent, CardMedia } from '@material-ui/core';



const cardStyle = ({

    cardMain:{
        maxWidth: '300px',
        maxHeight: '300px',
        margin: '10px',
    },

    cardImage:{
        height: '150px',
        backgroundImage: "url(" + "https://images.unsplash.com/photo-1517971129774-8a2b38fa128e?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=634&q=80" +  ")",
        marginLeft: '7px',
        marginRight: '7px',
        marginTop: '5px',
    },

});


const Produts = () =>{
    
    const [movieData, setMovieData] = useState([]);

    const getMovieList  = async () => {

        const url = 'http://api.themoviedb.org/3/search/movie?api_key=myapikey&query=Avengers';

        const response = await fetch (url);
                try {
                    const responseJson = await response.json();
                    console.log(responseJson);
                    setMovieData = (responseJson.results);
                } catch (err) {
                    console.error(err);
                }

    };

    useEffect (()=> {
     getMovieList();
    }, []);




    return (
        <> 
      
            <Card style={cardStyle.cardMain}>
                <CardActionArea>{setMovieData .original_title}
                    <CardMedia style = {cardStyle.cardImage}>{setMovieData .original_image}</CardMedia>
                    <CardContent>{setMovieData .original_date}</CardContent>

                </CardActionArea>
                <CardActions style = {cardStyle.cardButton}>
                    <Button>Watch</Button>
                    <Button>Like</Button>
                    <Button>Rent</Button>
                </CardActions>
            </Card>
        </>
    )
};
export default Produts;

Any help or suggestion is really appreciated.

  • function definition for the async call goes inside the useEffect unless you want to explore how useCallback works (much simpler not to)
  • the promise returned from fetch will return a response object of it doesn’t error, and that object has a json() function to parse the response.
useEffect(() => {
  const getData = async () => {
    const url = "http://api.themoviedb.org/3/search/movie?api_key=myapikey&query=Avengers";

    try {
      const resp = await fetch (url);
      const data = await resp.json();
      // Do anything you need to do to
      // data before this call:
      setMovieData(data);
    } catch (err) {
      console.error(err);
    }
  }

  getData();
}, []);
  • assuming the movies is always an array, you then map over it.
  • you need to provide a key for each item. That key needs to be unique: it doesn’t matter what it is as long as it’s unique, and I’ve assumed each movie object has an id.
  • because movies is an empty array when there’s no data, what will happen is that the component will render fine with no data (map works on empty arrays), but once the async request completes, the component will rerender with the data mapped
return (
  <>
    { movieData.map((movie) => (
      <Card style={someStyles} key={movie.id}>
        <RestOfCardStuff />
      </Card>
    )}
  </>
);

If you’re going to modify the query parameter (logical next step), add that as state then add that as a dependency to useEffect (means it will fire every time it changes), like so:

const [query, setQuery] = useState("");

useEffect(() => {
  const getData = async () => {
    const url = `http://api.themoviedb.org/3/search/movie?api_key=myapikey&query=${query}`;

    try {
      const resp = await fetch (url);
      const data = await resp.json();
      // Do anything you need to do to
      // data before this call:
      setMovieData(data);
    } catch (err) {
      console.error(err);
    } finally {
      setQuery("");
    }
  }

  if (query !== "") getData();
}, [query]);

To add error and loading, similar:

const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [query, setQuery] = useState("");

useEffect(() => {
  const getData = async () => {
    const url = `http://api.themoviedb.org/3/search/movie?api_key=myapikey&query=${query}`;
    setLoading(true);
    setError(null);

    try {
      const resp = await fetch (url);
      const data = await resp.json();
      // Do anything you need to do to
      // data before this call:
      setMovieData(data);
    } catch (err) {
      console.error(err);
      setError(err);
    } finally {
      setQuery("");
      setLoading(false);
    }
  }

  if (query !== "") getData();
}, [query]);
1 Like

Thanks a million, sir @DanCouper will surely give it a try step by step. if there is something else will get back to you. An this was one of the best explanations I have seen for all the codes you have written. Thanks again :slight_smile: :+1:

1 Like

Thank you :blush:. If anything isn’t clear, I’ll expand on it

1 Like

Hi @DanCouper

Thanks a million, I had to play around your answer back and forth and also read your statements. finally I got the answer.

Thanks again for your help and effort sir and the solution is below

const Produts = () =>{
    
    const [movieData, setMovieData] = useState([]);
    const getMovieList  = async () => {

        const url = 'http://api.themoviedb.org/3/search/movie?api_key=myapikey&query=Avengers';

        const response = await fetch (url);
                try {
                    const responseJson = await response.json();
                    const data = (responseJson.results);
                    setMovieData(data);
                } catch (err) {
                    console.error(err);
                }

    };

    useEffect (()=> {
       
     getMovieList();
    }, []);

    return (
        <> 
             {movieData.map((movie) =>{
                 return(
                    <Card style={cardStyle.cardMain} key={movie.id}>
                   <CardActionArea>
                       {movie.original_title}
                       <CardMedia style = {cardStyle.cardImage}>CardMedia</CardMedia>
                       <CardContent>cardContainer</CardContent>
   
                   </CardActionArea>
                   <CardActions style = {cardStyle.cardButton}>
                       <Button>Watch</Button>
                       <Button>Like</Button>
                       <Button>Rent</Button>
                   </CardActions>
               </Card>
                 );
                   
            })}
           
              
        </>
    )
};
export default Produts;
1 Like

Move the async function inside the useEffect, don’t put it outside it.

useEffect (() => {
  const response = async () {
    // doStuff
  };

  response();
}, []);

Not

const response = async () {
  // doStuff
};

useEffect (() => {
  response();
}, []);

You can’t put the response function outside the Product function, because response uses variables that only exist inside Product. If response didn’t use variables that only exist within Product, then that would be fine, but it does.

If you put response within the function body of Product but outside the useEffect function call, it will be recreated on every re-render. This isn’t a big issue in this case, as you’ve specified it should only run when the component renders for the very first time (the empty array that is the second argument to useEffect). But as soon as you start adding dependencies to that array, you make it very easy to create an infinite loop. So it is always good practice to have the function you are using in useEffect defined inside of useEffect.

1 Like

wow ! Thats a good guidance I have to say sir. Thanks a million. Thats what I was thinking around why there is need to use function inside useEffect and what does this thing do in real terms. @DanCouper thanks a million again for showing me the good practice tips and reason behind it. I really appreciate this one coming from experts like you.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.