[英]Trying to fetch data from a GraphQL API and then pass it as props to a component
I'm pretty now to GraphQL and TypeScript, so i'm trying to learn it by working with this API https://github.com/trevorblades/countries .我现在很喜欢 GraphQL 和 TypeScript,所以我正在尝试通过使用这个 API https://github.com/trevorblades/countries来学习它。 I'm trying to fetch data from the API to my React application in my HomeComponent and then pass the data to my CountryTable component, which is a Table component from the MUI library.
我试图从 API 获取数据到我的 HomeComponent 中的 React 应用程序,然后将数据传递到我的 CountryTable 组件,它是 MUI 库中的一个表组件。 But i get these error as "Argument of type is not assignable to parameter", "TypeError: countries.map is not a function".
但是我得到这些错误,因为“类型参数不可分配给参数”,“TypeError:countries.map 不是函数”。
This is how my HomeComponent looks like:这就是我的 HomeComponent 的样子:
import { Grid } from '@mui/material';
import Typography from '@mui/material/Typography';
import { ApolloClient, InMemoryCache, gql, useLazyQuery, ApolloProvider, useQuery, TypedDocumentNode} from '@apollo/client';
import { useEffect, useState } from 'react';
import React from 'react';
import CountryTable from '../components/CountryTable';
const client = new ApolloClient({
cache: new InMemoryCache(),
uri: 'https://countries.trevorblades.com'
});
const LIST_COUNTRIES = gql`
query getCountries {
countries {
name
code
capital
}}`;
export interface Country {
name: string;
code: string;
capital: string;
}
export interface Countries {
getAllCountries: Country[];
}
export default function Home() {
const {loading, data, error} = useQuery<Countries>(LIST_COUNTRIES, {client});
const [allcountries, setAllcountries] = useState([]);
useEffect(() => {
setAllcountries(data);
}, [data])
if (loading) return <p>Loading...</p>;
if (error) return <p>Error : {error.message}</p>;
return (
<ApolloProvider client={client}>
<Grid container alignItems="center" justifyContent="center">
<Grid item>
<CountryTable countries={allcountries}/>
</Grid>
</Grid>
</ApolloProvider>
)
}
And here is my CountryTable component:这是我的 CountryTable 组件:
import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
import { Country } from "../pages";
export interface CountryProps {
countries: Country[];
}
export default function CountryTable({countries}: CountryProps) {
return(
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="right">Name</TableCell>
<TableCell align="right">Code</TableCell>
<TableCell align="right">Capital</TableCell>
</TableRow>
</TableHead>
<TableBody>
{countries?.map((row: any) => (
<TableRow key={row.name}>
<TableCell align="right">{row.name}</TableCell>
<TableCell align="right">{row.code}</TableCell>
<TableCell align="right">{row.capital}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
The projectstructure: ProjectStructure项目结构: ProjectStructure
You are calling the useQuery
hook at the same level where the ApolloProvider
is being wrapped.您在包装
ApolloProvider
的同一级别调用useQuery
挂钩。
// Home.js
const {loading, data, error} = useQuery<Countries>(LIST_COUNTRIES, {client}); // 👈 same level
...
...
return (
<ApolloProvider client={client}> {/* 👈 Same level */}
..
..
</ApolloProvider>
)
The reason why moving the useQuery
hook you have from Home
to CountryTable
component worked is because now将您拥有的
useQuery
挂钩从Home
移动到CountryTable
组件的原因是因为现在
CountryTable
is inside ApolloProvider
. CountryTable
在ApolloProvider
里面。useQuery
hook can access the client
data it needed, which wasn't possible earlier when they were defined at the same level. useQuery
挂钩可以访问它需要的client
数据,这在之前它们被定义在同一级别时是不可能的。 To make it working in the same level, move the ApolloProvider
a level up.要使其在同一级别工作,请将
ApolloProvider
上移一个级别。
This can be either这可以是
Home
component if you have any or, Home
组件的父组件,如果有的话,_app.js
component if you're using NextJS
[1] _app.js
组件,如果你使用NextJS
[1] Reference:参考:
The problem why i could not fetch the data from the GraphQL API was because that my data that i was retrieving was as an whole object and the useState variabel which i'm using to save my data in so I can pass it as props to another component was an ArrayType of the interface Country.我无法从 GraphQL API 获取数据的问题是因为我正在检索的数据是一个整体 object 和我用来保存数据的 useState 变量,因此我可以将它作为道具传递给另一个component 是接口 Country 的 ArrayType。 So i have removed the interface Countries and then defined my const variabel as following:
所以我删除了接口 Countries,然后将我的 const variabel 定义如下:
const {loading, data, error} = useQuery<{countries: Country[]}>(LIST_COUNTRIES, {client});
const [allcountries, setAllcountries] = useState<Country[]>();
And then my component which receives the props have the following code:然后我接收道具的组件具有以下代码:
import { Box, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
import Link from "next/link";
import { useRouter } from "next/router";
import { FC } from "react";
import { Country } from "../pages";
export interface CountryProps {
countries: Country[] | undefined;
}
const CountryTable: FC<CountryProps> = ({countries}) => {
const router = useRouter();
return(
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="right">Name</TableCell>
<TableCell align="right">Code</TableCell>
<TableCell align="right">Capital</TableCell>
</TableRow>
</TableHead>
<TableBody>
{countries?.map(({name, code, capital}: Country) => (
<TableRow key={name}>
<TableCell align="right">
<Box>
<Link href={{pathname: "/detail/[name]", query: {name: name}}}>
{name}
</Link>
</Box>
</TableCell>
<TableCell align="right">{code}</TableCell>
<TableCell align="right">{capital}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
);
}
export default CountryTable;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.