You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+GraphQL+TypeScript数据传递报错求助:类型不匹配与map调用失败

问题解决:GraphQL + TypeScript + React 数据传递错误修复

核心错误原因

  1. 类型接口不匹配:Countries接口定义了getAllCountries字段,但GraphQL查询返回的结构是{ countries: Country[] },字段名不匹配导致TypeScript类型校验失败。
  2. 数据传递错误:直接将整个data对象(而非内部的countries数组)存入状态,子组件拿到的是对象而非数组,调用map方法自然报错。
  3. Apollo上下文错误:useQuery必须在ApolloProvider的上下文范围内执行,当前代码中useQuery先于ApolloProvider渲染,导致无法获取客户端实例。
  4. 冗余状态逻辑:无需额外用useState和useEffect存储数据,直接使用useQuery返回的结果即可。

分步修复代码

1. 修正类型定义(Home组件)

将Countries接口的字段改为countries,匹配GraphQL查询结果:

export interface Countries {
  countries: Country[];
}

2. 调整ApolloProvider位置(移到应用入口)

创建/修改App.tsx,将ApolloProvider作为根组件包裹Home,确保所有组件都能访问GraphQL客户端:

import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import Home from './pages/Home';

const client = new ApolloClient({
  cache: new InMemoryCache(),
  uri: 'https://countries.trevorblades.com'
});

function App() {
  return (
    <ApolloProvider client={client}>
      <Home />
    </ApolloProvider>
  );
}

export default App;

3. 简化Home组件逻辑

移除内部的客户端定义和ApolloProvider,直接传递正确的数组给子组件:

import { Grid } from '@mui/material';
import { useQuery, gql } from '@apollo/client';
import React from 'react';
import CountryTable from '../components/CountryTable';

const LIST_COUNTRIES = gql`
  query getCountries {
    countries {
      name
      code
      capital
  }}`;

export interface Country {
  name: string;
  code: string;
  capital: string;
}

export interface Countries {
  countries: Country[];
}

export default function Home() {
  const { loading, data, error } = useQuery<Countries>(LIST_COUNTRIES);

  if (loading) return <p>加载中...</p>;
  if (error) return <p>错误: {error.message}</p>;

  return (
    <Grid container alignItems="center" justifyContent="center">
      <Grid item>
        <CountryTable countries={data.countries} />
      </Grid>
    </Grid>
  )
}

4. 优化CountryTable组件

修正类型引用,替换any为正确的Country类型,同时处理无首都的情况:

import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material";
import { Country } from "../pages/Home";

export interface CountryProps {
    countries: Country[];
}

export default function CountryTable({ countries }: CountryProps) {
    return(
        <TableContainer component={Paper}>
            <Table sx={{ minWidth: 650 }} aria-label="国家列表表格">
                <TableHead>
                    <TableRow>
                        <TableCell align="right">名称</TableCell>
                        <TableCell align="right">代码</TableCell>
                        <TableCell align="right">首都</TableCell>
                    </TableRow>
                </TableHead>
                <TableBody>
                    {countries.map((row: Country) => (
                        <TableRow key={row.code}>
                        <TableCell align="right">{row.name}</TableCell>
                        <TableCell align="right">{row.code}</TableCell>
                        <TableCell align="right">{row.capital || '无'}</TableCell>
                    </TableRow>
                ))}
                </TableBody>
            </Table>
        </TableContainer>
    );
}

额外说明

  • 用国家代码code作为key比名称更可靠,避免同名国家导致的渲染问题。
  • 部分国家没有首都,添加|| '无'处理空值,避免显示空白。

内容的提问来源于stack exchange,提问作者menab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 06:01:00