【问题标题】:Cannot read property 'map' of undefined (ReactJS-Apollo-Graphql)无法读取未定义的属性“地图”(ReactJS-Apollo-Graphql)
【发布时间】:2020-07-06 18:22:31
【问题描述】:

我正在尝试使用 React JS 创建一个虚拟项目,并从 SpaceX Graphql API 获取我的数据。我有两个组件(主页、详细信息),两个组件都应该从 API 中获取数据。但是,我查询在 Home 组件中有效,但在 Details 组件中无效。我使用了完全相同的方法,但它似乎不起作用。请帮帮我。

如果您愿意,可以在https://github.com/affiqzaini/react-apollo-spacex 尝试整个过程。

这是我的 Home 组件,它可以工作:

import React from 'react';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';
import { BrowserRouter, NavLink } from 'react-router-dom';
import Route from 'react-router-dom/Route';
import 'react-bulma-components/dist/react-bulma-components.min.css';
import './App.css';
import Details from './Details';

const POSTS_QUERY = gql`
  {
    rockets {
      name
      country
      id
    }
  }
`;

function Home() {
  return (
    <BrowserRouter>
      <Route
        path='/'
        exact
        strict
        render={() => {
          return (
            <div
              className='tile is-ancestor'
              style={{
                justifyContent: 'space-evenly',
                alignItems: 'center',
                margin: 25
              }}
            >
              <Query query={POSTS_QUERY}>
                {({ loading, data }) => {
                  if (loading) return <p className='Loading'>Loading...</p>;
                  const { rockets } = data;
                  return rockets.map(post => (
                    <NavLink to={{ pathname: `/${post.id}` }}>
                      <div class='tile is-parent'>
                        <article
                          class='tile is-child box'
                          key={post.id}
                          style={{
                            backgroundColor: 'whitesmoke',
                            borderRadius: 10,
                            height: 400,
                            width: 300
                          }}
                        >
                          <figure
                            class='image container is-1by1'
                            style={{ marginBottom: 15 }}
                          >
                            <img
                              src={require(`./Images/${post.id.toString()}.jpg`)}
                              className='Rocket-Img'
                              alt='Rocket'
                            />
                          </figure>
                          <h2>{post.name}</h2>
                          <h4>{post.country}</h4>
                        </article>
                      </div>
                    </NavLink>
                  ));
                }}
              </Query>
            </div>
          );
        }}
      />
      <Route path='/:id' exact strict component={Details} />
    </BrowserRouter>
  );
}

export default Home;

这是我的详细信息组件不起作用:

import React from 'react';
import { useParams } from 'react-router';
import { Query, ApolloProvider } from 'react-apollo';
import gql from 'graphql-tag';
import ApolloClient from 'apollo-boost';
import './App.css';

function Details() {
  const rocketId = useParams();
  const QUERY_ROCKET = gql`
    {
      rocket(id: "${rocketId}") {
        id
        active
        boosters
        company
        cost_per_launch
        name
        stages
        success_rate_pct
        type
        wikipedia
        first_flight
        country
        description
      }
    }
  `;

  return (
    <Query query={QUERY_ROCKET}>
      {({ loading, data }) => {
        if (loading) {
          return <p className='Loading'>Loading...</p>;
        } else {
          const { detailsData } = data;
          return detailsData.map(post => (
            <div>
              <p>{post.id}</p>
            </div>
          ));
        }
      }}
    </Query>
  );
}
export default Details;

这是我得到的错误: Error Image

更新: 我发现我在两个查询中得到了不同类型的数据。在 Home(有效)中,我得到了一组数据。在我的详细信息组件中,我得到了一个对象。这就是我不能使用地图功能的原因吗?

【问题讨论】:

  • detailsData 未定义。您确定它已在您的 data 对象中返回吗?
  • 我确实得到了数据。但它不像 Home 组件那样在数组中。它只是一个对象。如何使用该对象?

标签: javascript reactjs graphql react-apollo map-function


【解决方案1】:

我发现我得到的数据是对象形式而不是数组。要访问该对象,您可以使用上述 DrewReese 的方法,也可以使用我认为更简单的方法:

*** 'rocket' 是我的对象的名称

return (
    <Query query={QUERY_ROCKET}>
      {({ loading, error, data }) => {
        if (loading) return <p className='Loading'>Loading...</p>;
        if (error) return `Error! ${error.message}`;

        const detailsData = data.rocket;
        return (
          <div>
            <p>{detailsData.id}</p>
            <p>{detailsData.name}</p>
            <p>{detailsData.company}</p>
            <p>{detailsData.stages}</p>
            <p>{detailsData.boosters}</p>
            <p>{detailsData.cost_per_launch}</p>
          </div>
        );
      }}
    </Query>

【讨论】:

  • 太棒了!我不熟悉graphQL,所以如果不深入研究一堆文档,我想我暂时不会得出这个结论。是的,如果您的结果对象 您要显示的对象,那么简单地访问字段/属性会更好,特别是如果您以不同的方式对待每个对象。不错。
【解决方案2】:

如果要映射的返回数据仍然是对象形式,则需要将对象转换为数组。

Object.values(data.detailsData) 获取just 值的数组,或Object.entries(data.detailsData) 获取键值对数组,即[[key1, value1], [key2, value2], ...[keyN, valueN]]

Object.values

Object.values() 方法返回给定对象自己的数组 可枚举的属性值,与 a 提供的顺序相同 for...in 循环。

Object.entries()

Object.entries() 方法返回给定对象自己的数组 可枚举字符串键控属性[key, value] 对,顺序相同 正如for...in 循环所提供的那样。

return Object.values(detailsData).map(post => (
  <div>
    <p>{post.id}</p>
  </div>
));

【讨论】:

    【解决方案3】:

    根据查询文档https://www.apollographql.com/docs/react/v2.5/essentials/queries/ 在此之后您不需要使用“else”:

    if (loading) return <p className='Loading'>Loading...</p>;
    

    而且您不会在有效的 Home 组件中执行此操作。尝试在您的详细信息组件中删除“else”:

    <Query query={QUERY_ROCKET}>
      {({ loading, data }) => {
        if (loading) return <p className='Loading'>Loading...</p>;
        const { detailsData } = data;
        return detailsData.map(post => (
          <div>
            <p>{post.id}</p>
          </div>
        ));
      }}
    </Query>
    

    【讨论】:

    • 我最初没有使用 else。它也没有用。我放它只是为了尝试其他东西,我忘了删除它。
    • 那么也许你可以试试这个: const { detailsData } = data && data;
    • 还是不行。如果您愿意,请随时尝试。 github.com/affiqzaini/react-apollo-spacex
    猜你喜欢
    • 2020-12-03
    • 2019-05-12
    • 2019-01-25
    • 1970-01-01
    • 2017-07-30
    • 2020-09-14
    • 2021-11-17
    • 2018-02-08
    • 2020-04-20
    相关资源
    最近更新 更多