为啥我不能用我的 api 响应更新我的状态?数据是一个对象数组

Posted

技术标签:

【中文标题】为啥我不能用我的 api 响应更新我的状态?数据是一个对象数组【英文标题】:why can i not update my state with my api response? data is an array of objects为什么我不能用我的 api 响应更新我的状态?数据是一个对象数组 【发布时间】:2021-04-15 00:46:54 【问题描述】:

我有两个返回 JSON 对象的 api 请求。它们返回一个对象数组。

我提出的一个 API 请求很好,允许我使用响应更新状态,但另一个(如下)没有,我不明白为什么。

获取流派列表的 API 请求:

 async getGenreList() 
    const genresResults = await getGenres();
    return genresResults;
  

请求:

export const getGenres = async () => 
  try 
    const response = await axios.get(
      "https://api.themoviedb.org/3/genre/movie/list?api_key=<APIKEY>&language=en-US"
    );
    const  genres  = response.data;
    return genres;
   catch (error) 
    console.error(error);
  
;

响应是一个包含 19 个流派对象的数组,但这只是一个示例:

[ 
id: 28, name: "Action",
id: 12, name: "Adventure"
]

然后我想像这样更新state 并将响应传递给genreOptions。但它告诉我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.

   componentDidMount() 
    this.getGenreList().then((response) => 
      console.log(response)
      this.setState( genreOptions: response);
    );
  

当我更新状态并对其进行映射时,以下内容有效,但我不想这样做,我想向下传递整个响应,以便我可以映射组件中的数据,因为我需要它在那里做一些数据匹配。

   this.setState( genreOptions: response.map((genreOption) => 
        return genreOption.name
   ));

这是状态:

  this.state = 
      results: [],
      movieDetails: null,
      genreOptions: [],
      
    ;

我想将这里的genreOptions 传递给genres,然后在MovieResults 组件中映射它。

 <MovieResults>
          totalCount > 0 && <TotalCounter>totalCount results</TotalCounter>
          <MovieList movies=results || [] genres=genreOptions || [] />

        </MovieResults>

为什么我不能?有任何想法吗?我已经为另一个类似的请求做了它:S

更新显示电影成分

export default class MovieList extends React.Component 
  render() 

    const  movies, genres  = this.props;
  
    const testFunction = (movieGenreIds) => 
    const matchMovieGenresAndGenreIds = genres.map((genreId) => 
      const matchedGenres = movieGenreIds.find((movieGenre) => 
        return movieGenre.id === genreId
      )
      return matchedGenres // this returns the matching objects
    )
      const result = matchMovieGenresAndGenreIds.filter(Boolean).map((el)=> 
      return el.name
    )
    return result
  
  
    return (
        <MoviesWrapper>
          movies.map((movie) => 
            const 
              title,
              vote_average,
              overview,
              release_date,
              poster_path,
              genre_ids
             = movie;
            return (
              <MovieItem
                title=title
                rating=vote_average
                overview=overview
                release=release_date
                poster=poster_path
                movieGenres=testFunction(genre_ids)

              />
            );
          )
        </MoviesWrapper>

    );
  

**** 电影项目组件***

export default class MovieItem extends React.Component 
  render() 
    const  title, overview, rating, release, poster, movieGenres  = this.props;
    return (
      // The MovieItemWrapper must be linked to the movie details popup
      <MovieItemWrapper>
        <LeftCont>
          <img
            className="movie-img"
            src=`https://image.tmdb.org/t/p/w500$poster`
          />
        </LeftCont>
        <RightCont>
         <div className="movie-title-container">
             <h2 className="movie-title">title</h2>
             <Rating>rating</Rating>
         </div>
             <div>movieGenres</div>
             <p>overview</p>
             <p>release</p>
        </RightCont>
      </MovieItemWrapper>
    );
  

【问题讨论】:

看来您的问题出在MovieList 组件中。你能发布它的代码吗?特别是渲染部分。 好的,我会发布,但它有点乱。在MovieList 组件中,我想使用genresgenreOptions 并将idgenreOption 与另一个数组中的ID 进行比较 - 用于上下文 别担心,继续。 完成,如果您需要更多关于我在做什么的解释,请告诉我。谢谢! 好吧,我或多或少明白你在做什么,但我很遗憾地告诉你,现在看来问题出在MovieItem 组件内部(我希望你终于试图使用您处理过的数组)。我还看到了其他一些问题,但要完全回答我需要您发布MovieItem 代码。 【参考方案1】:

请按照此步骤修复您的代码。我会试着解释一下一路上发生的事情:

    在您的主要组件中。将状态设置为您真正想要传递给子组件的值。请记住,response 将是一个对象数组。
componentDidMount() 
    this.getGenreList().then((response) => 
        this.setState(genreOptions: response);
    );

    在您的MovieList 组件中。请检查您的testFunction 以尊重数据类型。以下代码将返回一个字符串数组,其中包含电影流派数组中包含的流派名称。
const testFunction = (movieGenreIds) => 
    return genres
        .filter((genre) => 
            return movieGenreIds.includes(genre.id);
        )
        .map((genre) => genre.name);
;
    在您的MovieItem 组件中。 (这才是真正的问题所在)

代替:

<div>movieGenres</div>

你可能想做这样的事情:

<div>movieGenres.join(' ')</div>

这会将您的数组转换为可以呈现的字符串。您的错误是由于您向那里传递了一个 React 无法呈现的对象数组。

如果您有任何疑问,请告诉我。

注意:我建议您使用类型检查器来避免此类问题。并与您的变量命名约定保持一致。


根据聊天中的新信息进行更新:

    在您的ExpandableFilters 组件中,您必须修复以下代码以获取流派名称(字符串)。正如聊天中所解释的,您不能将对象作为 JSX 表达式 () 的结果,而只能是可以强制转换为字符串、JSX 元素或 JSX 元素数组的原语。
<GenreFilterCont marginTop>
    filtersShown && (
        <ExpandableFiltersUl>
            this.props.movieGenres.map((genre, index) => 
                return (
                    <ExpandableFiltersLi key=index>
                        <Checkbox />
                        genre.name
                    </ExpandableFiltersLi>
                );
            )
        </ExpandableFiltersUl>
    )
</GenreFilterCont>

还请注意,我添加了 key 属性。只要有要渲染的元素列表,就应该这样做。有关此的更多信息,我将向您推荐React Docs。

【讨论】:

非常感谢!好的,所以我了解到的是,我实际上能够使用来自 API 请求的响应来更新state,该请求是一个对象数组,但是我无法从 API 呈现该对象/对象数组作为结果一个 JSX 表达式。在您更正我的代码之前,我在 ExpandableFilters 中渲染了 genre,这实际上是一个对象,所以它不起作用,它给了我错误 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.

以上是关于为啥我不能用我的 api 响应更新我的状态?数据是一个对象数组的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能用我的 JWK 签署这些声明?

Reactjs - 为啥我不能设置状态?

为啥我的微 API 没有响应体?

为啥我的rest api post请求不能将我的数组保存在我的mongodb数据库中

多次响应实时数据获取

为啥我的前端 Javascript 显示的 API 响应与浏览器不同? [复制]