如何在 React 中使用 Graphql typescript 类型

How to use Graphql typescript types in react

我有一个带有 keystone.js 后端和 graphql api

的 React 应用程序

我在 keystones.js 中有一个产品列表和一个简单的 graphql 查询

import gql from "graphql-tag";

export const ALL_PRODUCTS_QUERY = gql`
    query ProductData{
        allProducts{
            id
            price
            description
            name
        }
    }
`

我正在使用 apollo codegen 生成 graphql 的类型,所以我得到

export interface ProductData_allProducts {
  __typename: "Product";
  id: string;
  price: number | null;
  description: string | null;
  name: string | null;
}

export interface ProductData {
  /**
   *  Search for all Product items which match the where clause. 
   */
  allProducts: (ProductData_allProducts | null)[] | null;
}

在 React 中我可以列出产品并使用代码中的类型,这里我使用 <ProductData>

import { useQuery } from "@apollo/client";
import {ALL_PRODUCTS_QUERY} from '../queries/index'
import { ProductData } from "../generated/ProductData";

const Products = () => {

    const {data, error, loading} = useQuery<ProductData>(ALL_PRODUCTS_QUERY)
    if(loading) return <p>Loading</p>
    if(error) return <p>Error: {error.message}</p> 

    return (
        <div>
            <div>
                {data?.allProducts?.map(product => (
                    <div>{product?.name}</div>
                ))}
            </div>
        </div>
    );
};

export default Products;

而不是使用 <div>{product?.name}</div> 我想创建一个 Product 组件

import React from 'react';
import { ProductData, ProductData_allProducts } from '../generated/ProductData';

const Product = ({product}:ProductData_allProducts) => {
    return (
        <p>{product.name}</p>
    );
};

export default Product; 

但是 product 的类型应该是什么 我收到一条错误消息说

Property 'product' does not exist on type 'ProductData_allProducts'.    

在产品页面上

import { useQuery } from "@apollo/client";
import {ALL_PRODUCTS_QUERY} from '../queries/index'
import { ProductData } from "../generated/ProductData";
import Product from "./Product";


const Products = () => {

    const {data, error, loading} = useQuery<ProductData>(ALL_PRODUCTS_QUERY)
    if(loading) return <p>Loading</p>
    if(error) return <p>Error: {error.message}</p> 

    return (
        <div>
            <div>
                {data?.allProducts?.map(product => (
                    <Product product={product} />
                ))}
            </div>
        </div>
    );
};

export default Products;    

我现在在产品道具上遇到错误

Type '{ product: ProductData_allProducts | null; }' is not assignable to type 'IntrinsicAttributes & ProductData_allProducts'.
  Property 'product' does not exist on type 'IntrinsicAttributes & ProductData_allProducts'.    

那么传入产品时,产品页面上的类型应该是什么

您正在尝试解构类型上不存在的 属性。
这应该有效:

type Product = {
  __typename: "Product";
  id: string;
  price: number | null;
  description: string | null;
  name: string | null;
};

const ProductComponent: FC<Product> = ({ name }) => {
  return <p>{name}</p>;
};

export default ProductComponent;

以下对你有用吗?

interface ProductComponentProps {
    product: ProductData_allProducts
}


const Product = ({product}: ProductComponentProps) => {
    return (
        <p>{product.name}</p>
    );
};

解决方案

您可以像这样更改代码来修复错误:

const Product = ({ product }: { product: ProductData_allProducts }) => {
  return <p>{product.name}</p>;
};

说明

问题是您将组件的 props 键入为类型 ProductComponentProps,而您一直只想键入 属性 props.product。所以你的代码基本上是这样的:

const Product = (props: ProductData_allProducts) => {
  return (
      <p>{product.name}</p>
  );
};

由于缺少 namedescription 等所有属性,Typescript 对此进行了投诉。这是一个工作 codesandbox 供您查看。