#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. Спасибо. Да, понял, что я делал не так.