Не удается прочитать свойство 'map' из неопределенного (ReactJS -Apollo-Graphql) - PullRequest
0 голосов
/ 26 марта 2020

Я пытаюсь создать фиктивный проект с React JS, и я получаю свои данные из API SpaceX Graphql. У меня есть два компонента (Home, Details), и оба компонента должны получать данные из 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;

Вот мой компонент Details, который не работает:

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;

Вот ошибка, которую я получаю: Изображение ошибки

Обновление: я обнаружил, что получаю другой тип данных в двух запросах. В Home (который работает) я получаю массив данных. В моем компоненте деталей я получаю объект. Поэтому я не могу использовать функцию карты?

Ответы [ 3 ]

1 голос
/ 26 марта 2020

В соответствии с документами Query https://www.apollographql.com/docs/react/v2.5/essentials/queries/ вам не нужно использовать «else» после этого:

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

И вы не делаете этого в своем компоненте Home, который работает. Попробуйте также удалить «else» в вашем компоненте Details:

<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>
0 голосов
/ 26 марта 2020

Я обнаружил, что данные, которые я получаю, находятся в форме объекта, а не в виде массива. Чтобы получить доступ к объекту, вы можете использовать метод 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>
0 голосов
/ 26 марта 2020

Если возвращаемые данные, которые вы хотите отобразить, все еще находятся в форме объекта, вам необходимо преобразовать объект в массив.

Object.values(data.detailsData), чтобы получить массив из просто значений или Object.entries(data.detailsData) для получения массива пар ключ-значение, например [[key1, value1], [key2, value2], ...[keyN, valueN]].

Object.values ​​

Метод Object.values() возвращает массив значений перечислимых свойств данного объекта в том же порядке, что и for...in l oop.

Object.entries ()

Метод Object.entries() возвращает массив собственных перечисляемых строковых ключей [key, value] собственного перечисленного объекта с указанным объектом в том же порядке, что и for...in l oop.

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