Не удается прочитать свойство «реквизит» неопределенного React-graphql

#javascript #reactjs #react-router #graphql

Вопрос:

Я следую учебнику по graphql от traversery media и пытаюсь создать небольшое приложение только для чтения из api SpaceX. Все остальное работает нормально, но когда я пытаюсь реализовать код из его учебника, у меня возникают проблемы. Если кто-нибудь читает это, пожалуйста, сравните код, так как я новичок, и все могло измениться. Я помещу его фрагмент кода, а затем свой, чтобы показать читателю, в чем именно разница. Его APP.js является

 import React, { Component } from 'react';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Launches from './components/Launches';
import Launch from './components/Launch';
import './App.css';
import logo from './logo.png';

const client = new ApolloClient({
uri: 'http://localhost:5000/graphql'
});

class App extends Component {
render() {
return (
  <ApolloProvider client={client}>
    <Router>
      <div className="container">
        <img
          src={logo}
          alt="SpaceX"
          style={{ width: 300, display: 'block', margin: 'auto' }}
        />
        <Route exact path="/" component={Launches} />
        <Route exact path="/launch/:flight_number" component={Launch} />
      </div>
    </Router>
  </ApolloProvider>
);
}
}

export default App;
 

и его Lunch.js

 import React, { Component, Fragment } from 'react';
import gql from 'graphql-tag';
import { Query } from 'react-apollo';
import { Link } from 'react-router-dom';
import classNames from 'classnames';

const LAUNCH_QUERY = gql`
query LaunchQuery($flight_number: Int!) {
launch(flight_number: $flight_number) {
  flight_number
  mission_name
  launch_year
  launch_success
  launch_date_local
  rocket {
    rocket_id
    rocket_name
    rocket_type
  }
}
}
`  ;

export class Launch extends Component {
 render() {
 let { flight_number } = this.props.match.params;
  flight_number = parseInt(flight_number);
 return (
  <Fragment>
    <Query query={LAUNCH_QUERY} variables={{ flight_number }}>
      {({ loading, error, data }) => {
        if (loading) return <h4>Loading...</h4>;
        if (error) console.log(error);

        const {
          mission_name,
          flight_number,
          launch_year,
          launch_success,
          rocket: { rocket_id, rocket_name, rocket_type }
        } = data.launch;

        return (
          <div>
            <h1 className="display-4 my-3">
              <span className="text-dark">Mission:</span> {mission_name}
            </h1>
            <h4 className="mb-3">Launch Details</h4>
            <ul className="list-group">
              <li className="list-group-item">
                Flight Number: {flight_number}
              </li>
              <li className="list-group-item">
                Launch Year: {launch_year}
              </li>
              <li className="list-group-item">
                Launch Successful:{' '}
                <span
                  className={classNames({
                    'text-success': launch_success,
                    'text-danger': !launch_success
                  })}
                >
                  {launch_success ? 'Yes' : 'No'}
                </span>
              </li>
            </ul>

            <h4 className="my-3">Rocket Details</h4>
            <ul className="list-group">
              <li className="list-group-item">Rocket ID: {rocket_id}</li>
              <li className="list-group-item">
                Rocket Name: {rocket_name}
              </li>
              <li className="list-group-item">
                Rocket Type: {rocket_type}
              </li>
            </ul>
            <hr />
            <Link to="/" className="btn btn-secondary">
              Back
            </Link>
          </div>
        );
      }}
    </Query>
    </Fragment>
  );
  }
 }

export default Launch;
 

Mine App.js is

 import { ApolloProvider } from '@apollo/client/react';
import { ApolloClient, InMemoryCache } from '@apollo/client';
import { BrowserRouter as Router, Route } from "react-router-dom";
import Launches from './components/Lanches';
import Launch from './components/Launch';
import logo from './logo.png';
import './App.css';


const client = new ApolloClient({
uri: 'http://localhost:5000/graphql',
cache: new InMemoryCache()
});

function App() {
return (
<ApolloProvider client={client}>
  <Router>
    <div className="container">
      <img
        src={logo}
        alt="SpaceX"
        style={{ width: 300, display: 'block', margin: 'auto' }}
      />
      <Route exact path="/" component={Launches} />
      <Route exact path="/launch/:flight_number" component={Launch} />


    </div>
  </Router>
  </ApolloProvider>
 );
 }

 export default App;
 

Моя Launch.js

 import React, { Fragment } from 'react';
import { useQuery,gql } from '@apollo/client';
import {Link} from 'react-router-dom';
import classNames from 'classnames';

const LAUNCH_QUERY =gql`
query LaunchQuery($flight_number: Int) {
launch(flight_number: $flight_number) {
  flight_number
  mission_name
  launch_year
  launch_success
  launch_date_local
  rocket {
    rocket_id
    rocket_name
    rocket_type
  }
}
}
`;


const Launch = () => {
let {flight_number} = this.props.match.params;
const { loading, error, data } = useQuery(LAUNCH_QUERY, {variables:{flight_number}});

if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
console.log(error)
  console.log(data)

return (

 <div>
   {data}
 </div>
);
}


export default Launch;
 

Но когда я делаю то let {flight_number= this.props.match.params}

он показывает неопределенное и выдает ошибку TypeError: Не удается прочитать свойство «реквизит» неопределенного PS: Я новичок и был бы очень признателен, если бы кто-нибудь сказал мне, что я должен делать ?

Комментарии:

1. нет this в ФК

Ответ №1:

Ваша проблема связана с классом и функциональными компонентами, ваш Launch компонент является функциональным, в то время как его-класс. В this функциональных компонентах нет ключевого слова.

Если вы хотите получить доступ к реквизитам в функциональном компоненте, вам нужно будет передать их в качестве параметров, но, поскольку вы следуете учебнику, вам, вероятно, следует просто переработать свой код для использования классов.

Вот блог, если вы хотите прочитать больше: https://www.twilio.com/blog/react-choose-functional-components

Комментарии:

1. прочтите это сами … предлагать рефакторинг в класс просто неправильно, достаточно явно определить/передать реквизиты … вы можете свободно смешивать класс и ФК … компоненты запроса рендеринга устарели

2. Спасибо. Да, понял, что я делал не так.