简体   繁体   English

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

[英]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 . CountryTableApolloProvider里面。
  • The 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这可以是

  • The parent component of Home component if you have any or, Home组件的父组件,如果有的话,
  • The _app.js component if you're using NextJS [1] _app.js组件,如果你使用NextJS [1]

Reference:参考:

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

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.

相关问题 如何从api获取数据并将其作为道具传递 - How to fetch data from api and pass it as props 从 mongoDB、setstate 获取数据并将 props 传递给子组件不起作用 - fetch data from mongoDB, setstate and pass props to child component is not working 如何从 GraphQL API 获取数据并将其传递给其他函数文件? - How to fetch data from GraphQL API and pass it to other function file? 最初获取数据并将 props 传递给另一个组件 - Initially fetch data and pass props to another component 如何将从 graphql API 获取的数据传递给 React class 组件 - How to pass data fetched from graphql API to React class component React:如何将数据作为道具从2个不同的API传递到单个组件 - React: How to pass data from 2 different API as props to a single component React 如何将道具从 api 传递给组件? - How React pass props from api to component? 根据组件属性从API提取数据 - Fetch data from API depending on the components props 如何将从 API 获取的数据作为道具传递给其路由在 React JS 的另一个页面中定义的组件? - How to pass data fetched from an API as props to a component whose routes is defined in another page in React JS? 如何从长获取调用函数中传递数据作为React中的props - How to pass data from a long fetch call function as props in React
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM