typescript 尝试从GraphQL API获取数据,然后将其作为属性传递给组件

2guxujil  于 2023-01-10  发布在  TypeScript
关注(0)|答案(1)|浏览(101)

我现在很熟悉GraphQL和TypeScript,所以我尝试通过使用这个API https://github.com/trevorblades/countries来学习它。我尝试从API中提取数据到我的HomeComponent中的React应用程序,然后将数据传递到我的CountryTable组件,这是MUI库中的一个表组件。但是我收到了这些错误,如“类型的参数不可分配给参数”、“TypeError:countries.map不是函数””。
这是我的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>
  )
}

这是我的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>
    );
}

项目结构:ProjectStructure

koaltpgm

koaltpgm1#

您将在 Package ApolloProvider的同一级别调用useQuery钩子。

// Home.js
const {loading, data, error} = useQuery<Countries>(LIST_COUNTRIES, {client}); // 👈 same level
...
...
return (
    <ApolloProvider client={client}> {/* 👈 Same level */}
      ..
      ..
    </ApolloProvider>
)

useQuery钩子从Home移动到CountryTable组件的原因是,现在

  • CountryTable位于ApolloProvider内部。
  • useQuery钩子可以访问它所需要的client数据,这在以前它们被定义在同一级别时是不可能的。

要使其在同一级别中工作,请将ApolloProvider向上移动一个级别。
这可以是

  • Home组件的父组件(如果有)或,
  • _app.js组件(如果您使用的是NextJS)[1]

参考:

  1. https://nextjs.org/docs/advanced-features/custom-app

相关问题