Reputation: 57
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. 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. But i get these error as "Argument of type is not assignable to parameter", "TypeError: countries.map is not a function".
This is how my HomeComponent looks like:
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:
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
Upvotes: 1
Views: 202
Reputation: 57
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. So i have removed the interface Countries and then defined my const variabel as following:
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;
Upvotes: 1