0

disclaimer: I have checked other threads such as this one and can see that my issue is not technically the same:Promise Error: Objects are not valid as a React child

I have sent my api request:

async getGenreList(){
    const genresResults = await getGenres()
     return genresResults
  }

  componentDidMount() {
    this.getGenreList().then((response) => {
      this.setState({ genreOptions: response})
    });
    
  }

here is the response: each object includes an id and name key

(19) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]

in the state genreOptions is expecting an array

  this.state = {
      totalCount: 0,
      genreOptions: [],
    };

I pass genreOptions to the MovieList component where I then map over the genreOptions

<MovieList movies={results || []} genres={genreOptions || []} />

inside MovieList component

 {genres.map((genre)=>{
      return <div>{genre.id} {genre.name}</div>
 })}

I am mapping over the array of objects that I got back from my Promise, so I am not sure why I am getting the error. Error: Objects are not valid as a React child (found: object with keys {id, name}). If you meant to render a collection of children, use an array instead.

Please let me know if you spot it.

Thanks in advance.

UPDATE TO SHOW WHAT ONE OF OBJECTS LOOKS LIKE

0:
id: 28
name: "Action"
__proto__: Object

UPDATE TO SHOW FULL MOVIELIST COMPONENET

export default class MovieList extends React.Component {
  render() {
    const { movies, genres } = this.props;

    return (
      <MoviesWrapper>
        {movies.map((movie) => {
          return <div>{movie.title}</div>;
        })}
          {genres.map((genre)=>{
              return <div>{genre.id} {genre.name}</div>
          })}
      </MoviesWrapper>
    );
  }
}

*** a solution i came up with but not sure that i should use .map when updating the state ***

 this.getGenreList().then((response) => {
      this.setState({ genreOptions: response.map((genre) => genre.name)})
    });

This returns an array of names

Angela Inniss
  • 359
  • 1
  • 2
  • 18
  • Hi Angela, can you include an example of one of the objects in the array so we can see exactly what data you are trying to render? – Chris Jan 07 '21 at 23:58
  • Actually I might have spotted it - could you show us the full MovieList component? Is the array map inside any jsx? If not, then you shouldn’t be wrapping it in curly braces. That would cause an error – Chris Jan 08 '21 at 07:19
  • Hello @Chris I have updated the question to show what is in one object in the array of objects i get back and i have added the `movieList` component – Angela Inniss Jan 08 '21 at 09:58
  • @Chris i found a solution to extract the move genres but i am not sure this is the way to do it.... Id rather update the state as an array of objects then map over the data i need in the `movieList` component. I have added my solution above also but please let me know if you have a better way. – Angela Inniss Jan 08 '21 at 10:06
  • 1
    Hi Angela, it’s fine setting the state like that - really you’re setting the state to the result of the map function. You could make it more explicit by assigning the result of the map function to a variable and then using that variable to update the state, but it’s the same thing in the end, just easier to read. If this works for you then great, but it doesn’t explain why it wasn’t working before - the error you got means it was trying to render an object as the contents of the div, rather than the number/string properties on that object - I.e it’s as if you had written
    {genre}
    – Chris Jan 08 '21 at 10:56
  • Thank you for the explanation about setState, I think i will use a variable as it will look cleaner. This is good to know for future reference. – Angela Inniss Jan 08 '21 at 12:38
  • 1
    Hi, sorry I deleted my answer - it was incorrect what I said about rendering children - but your comment on my answer prompted me to think that perhaps it's because the MoviesWrapper component is not returning any jsx, but just returning the children. In that case it would be possible to cause an error by passing the 2 arrays as children, and would explain why wrapping it in a fragment would work for you. – Chris Jan 08 '21 at 18:24
  • I have another question about this. What if i want to set the state to the response of my API call? I want the updated state for `genreOptions: [ ],` to be the array of 19 objects. Then when I pass it down to the `MovieList` component I want to map over the data there why is this not possible? – Angela Inniss Jan 09 '21 at 13:21
  • 1
    Have you tried this now that you have resolved the original error? It should be perfectly possible and is common practice. Just keep in mind that you’ll need to think about how to implement the map function - if you just put it as a simple function in the MovieList component then it will run on every render - that might not be a big problem depending on the size of your app, but if performance is an issue you should consider things like memoization – Chris Jan 09 '21 at 19:48

1 Answers1

0

issue was that i was returning and object inside of JSX parenthesis in one of my components which also housed movieGenres

<GenreFilterCont marginTop>
 {filtersShown && (
   <ExpandableFiltersUl>
 {this.props.movieGenres.map((genre) => {
 return (
     <ExpandableFiltersLi>
       <Checkbox />
         {genre} //here
     </ExpandableFiltersLi>
       );
      })}
    </ExpandableFiltersUl>
 )}
 </GenreFilterCont>

indstead of


<GenreFilterCont marginTop>
              {filtersShown && (
                  <ExpandableFiltersUl>
                      {this.props.movieGenres.map((genre, index) => {
                          return (
                              <ExpandableFiltersLi key={index}>
                                  <Checkbox />
                                  {genre.name} //here is correct and not an object
                              </ExpandableFiltersLi>
                          );
                      })}
                  </ExpandableFiltersUl>
              )}
          </GenreFilterCont>

Angela Inniss
  • 359
  • 1
  • 2
  • 18