React-TypeScript: This JSX tag's 'children' prop expects a single child of type 'ReactNode', but multiple children were provided

Viewed 4266

I am using react-typescript for a class project in APIs, and am having issues. I am trying to use .map to loop through an array of "popular" movies, but am getting the error message "This JSX tag's 'children' prop expects a single child of type 'ReactNode', but multiple children were provided." I have a single div tag as the "parent", so I don't understand why it is giving me this error. When I take the loop out and just put regular elements, I don't get the error message. Sorry if I'm not wording it too great, I'm still fairly new to this.

Here is my Popular component

import React, { useEffect, useState } from 'react';
import Genres from '../models/Genres';
import Results from '../models/Popular';
import GenreListService from '../services/GenreList';
import getPopular from '../services/GetPopular';


export default function Popular() {
    const[popular, setPopular] = useState<Results[]>()
    const [genres, setGenres] = useState<Genres[]>()
    useEffect(() => {
        getPopular().then(data => {
            setPopular(data);
        });
    }, []);
    useEffect(() => {
        GenreListService().then(data => {
            setGenres(data);
        });
    }, []);
  return (
    <div className="Popular"> {/* This is where I get the error message */}
        <h1>POPULAR MOVIES</h1>
            {   
                popular?.map((thing, index) => {
                    <div key={index}>
                        <p>{thing.title}</p>
                        <p>{thing.overview}</p>
                        <p>{thing.genre_ids}</p>
                    </div>
                })
            }
    </div>
  )
}

Here is my Popular interface

export interface Popular {
    results: Results[]
}

export default interface Results {
    backdrop_path: string,
    genre_ids: number[],
    id: number,
    overview: string,
    poster_path: string,
    release_date: string,
    title: string,
    vote_average: 6.8,
}

And here is the API I got it from.

import axios from "axios";
import Results, { Popular } from "../models/Popular";

export default function getPopular(): Promise<Results[]>{
    return axios
        .get<Popular>("https://api.themoviedb.org/3/movie/popular?api_key={api-key}")
        .then((response) => {return response.data.results})
}

ANY input would be greatly appreciated!!

2 Answers

Update: I figured it out. I needed to get rid of the curly brackets inside of the .map loop

To complement the answer.

The issue was that your .map iterated with a void function (a function that doesn't return anything).

You had 2 options:

  • Adding a return;
  • Removing brackets.

When working with Arrow Functions, you can write a single-line function that returns it's only statament.

This:

[1, 2].map((integer) => {
  return integer + 1
})

It the same as this:

[1, 2].map((integer) => integer + 1)

Both return integer + 1, but only the first must to explicit call for return, or else nothing is returned.


By removing return, you end up with an array of undefined. Here is a snippet to help with visualizing it:

result1 = [1, 2].map((integer) => {
  return integer + 1
})
console.log(result1) // > [2, 3]

result2 = [1, 2].map((integer) => integer + 1)
console.log(result2) // > [2, 3]

result3 = [1, 2].map((integer) => {
  integer + 1
})
console.log(result3) // > [undefined, undefined]

Related