检索路由器查询对象后调用 useQuery(带有 GraphQL 的 NextJS)
Call useQuery after retrieving router query object (NextJS with GraphQL)
我正在使用以下方法在 NextJS 中检索查询参数:
const qry_flightNumber = Number(router.query.flightNumber);
然后我想通过这样做向我的 GraphQL 服务器发送请求:
页数:LaunchDetails.js
import React, { useEffect, useState } from "react";
import classNames from "classnames";
import gql from "graphql-tag";
import { useQuery } from "@apollo/react-hooks";
import PropTypes from "prop-types";
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 default function LaunchDetails({ flightNum }) {
const { loading, error, data } = useQuery(LAUNCH_QUERY, {
variables: { flight_number: flightNum },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
console.log("data.launch: ", data.launch);
const flightNumber = data.launch.flight_number;
const launchDate = data.launch.launch_date_local;
const launchSuccess = data.launch.launch_success;
const launchYear = data.launch.launch_year;
const missionName = data.launch.mission_name;
const { rocket } = data.launch;
return (
<div>
<h1 className="display-4 my-3">
<span className="text-dark">Mission: {missionName}</span>
</h1>
<h2 className="mb-3">Launch details</h2>
<ul className="list-group">
<li className="list-group-item">Flight number: {flightNumber}</li>
<li className="list-group-item">Launch year: {launchYear}</li>
<li className="list-group-item">
Launch successful:{" "}
<span
className={classNames({
"text-success": launchSuccess,
"text-danger": launchSuccess === false,
})}
>
{launchSuccess ? "yes" : "no"}
</span>
</li>
</ul>
<h4 className="my-3">Rocket details:</h4>
<ul className="list-group">
<li className="list-group-item">Rocket ID: {rocket.rocket_id}</li>
<li className="list-group-item">Rocket name: {rocket.rocket_name}</li>
<li className="list-group-item">Rocket type: {rocket.rocket_type}</li>
</ul>
<hr />
</div>
);
}
LaunchDetails.propTypes = {
flightNum: PropTypes.number.isRequired,
};
包含组件 ([flight_number].js) 的动态页面:
import { ApolloProvider } from "@apollo/react-hooks";
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import APOLLO_CLIENT from "../../graphql/config";
import LaunchDetails from "../../components/launches/LaunchDetails";
export default function Home() {
const router = useRouter();
const flightNum = Number(router.query.flightNumber);
return (
<>
{/* <Head>
<title>SpaceX launch</title>
</Head> */}
<ApolloProvider client={APOLLO_CLIENT}>
<div className="container">
<h1 className="title">Apollo launch details</h1>
<LaunchDetails flightNum={flightNum} />
<Link href="/">
<a className="btn btn-secondary">Back</a>
</Link>
</div>
</ApolloProvider>
</>
);
}
问题在于,在第一个页面加载时,GraphQL 查询执行时 flight_number 为空。所以我最终在控制台中收到此警告:
[GraphQL error]: Message: Variable "$flight_number" of non-null type "Int!" must not be null., Location: [object Object], Path: undefined
我已经尝试使用 IF 语句来确保 flight_number 在 运行 查询之前是 !NaN 但是 React 抱怨调用挂钩的顺序。
显然在组件完全加载后,GraphQl 变量被定义并正确执行,但是我仍然会收到控制台警告。
控制台警告截图:
停止控制台警告的选项有哪些?
谢谢。
我现在已经得到了答案。您可以将 skip 参数传递给 useQuery 以仅在定义变量或未定义 NaN 时才执行查询:
const { loading, error, data } = useQuery(LAUNCH_QUERY, {
variables: { flight_number: flightNum },
skip: Number.isNaN(flightNum),
});
我正在使用以下方法在 NextJS 中检索查询参数:
const qry_flightNumber = Number(router.query.flightNumber);
然后我想通过这样做向我的 GraphQL 服务器发送请求:
页数:LaunchDetails.js
import React, { useEffect, useState } from "react";
import classNames from "classnames";
import gql from "graphql-tag";
import { useQuery } from "@apollo/react-hooks";
import PropTypes from "prop-types";
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 default function LaunchDetails({ flightNum }) {
const { loading, error, data } = useQuery(LAUNCH_QUERY, {
variables: { flight_number: flightNum },
});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
console.log("data.launch: ", data.launch);
const flightNumber = data.launch.flight_number;
const launchDate = data.launch.launch_date_local;
const launchSuccess = data.launch.launch_success;
const launchYear = data.launch.launch_year;
const missionName = data.launch.mission_name;
const { rocket } = data.launch;
return (
<div>
<h1 className="display-4 my-3">
<span className="text-dark">Mission: {missionName}</span>
</h1>
<h2 className="mb-3">Launch details</h2>
<ul className="list-group">
<li className="list-group-item">Flight number: {flightNumber}</li>
<li className="list-group-item">Launch year: {launchYear}</li>
<li className="list-group-item">
Launch successful:{" "}
<span
className={classNames({
"text-success": launchSuccess,
"text-danger": launchSuccess === false,
})}
>
{launchSuccess ? "yes" : "no"}
</span>
</li>
</ul>
<h4 className="my-3">Rocket details:</h4>
<ul className="list-group">
<li className="list-group-item">Rocket ID: {rocket.rocket_id}</li>
<li className="list-group-item">Rocket name: {rocket.rocket_name}</li>
<li className="list-group-item">Rocket type: {rocket.rocket_type}</li>
</ul>
<hr />
</div>
);
}
LaunchDetails.propTypes = {
flightNum: PropTypes.number.isRequired,
};
包含组件 ([flight_number].js) 的动态页面:
import { ApolloProvider } from "@apollo/react-hooks";
import React from "react";
import Link from "next/link";
import { useRouter } from "next/router";
import APOLLO_CLIENT from "../../graphql/config";
import LaunchDetails from "../../components/launches/LaunchDetails";
export default function Home() {
const router = useRouter();
const flightNum = Number(router.query.flightNumber);
return (
<>
{/* <Head>
<title>SpaceX launch</title>
</Head> */}
<ApolloProvider client={APOLLO_CLIENT}>
<div className="container">
<h1 className="title">Apollo launch details</h1>
<LaunchDetails flightNum={flightNum} />
<Link href="/">
<a className="btn btn-secondary">Back</a>
</Link>
</div>
</ApolloProvider>
</>
);
}
问题在于,在第一个页面加载时,GraphQL 查询执行时 flight_number 为空。所以我最终在控制台中收到此警告:
[GraphQL error]: Message: Variable "$flight_number" of non-null type "Int!" must not be null., Location: [object Object], Path: undefined
我已经尝试使用 IF 语句来确保 flight_number 在 运行 查询之前是 !NaN 但是 React 抱怨调用挂钩的顺序。
显然在组件完全加载后,GraphQl 变量被定义并正确执行,但是我仍然会收到控制台警告。
控制台警告截图:
停止控制台警告的选项有哪些? 谢谢。
我现在已经得到了答案。您可以将 skip 参数传递给 useQuery 以仅在定义变量或未定义 NaN 时才执行查询:
const { loading, error, data } = useQuery(LAUNCH_QUERY, {
variables: { flight_number: flightNum },
skip: Number.isNaN(flightNum),
});