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

Vite React集成HygraphCMS出现400 Bad Request错误求助

问题:添加GridText模块后GraphQL请求返回400错误,移除则恢复正常

我在Vite React项目中遇到了一个问题:当添加GridText模块后,页面数据(pageData)无法加载,返回400 BAD REQUEST错误;但只要移除GridText相关代码,请求就能正常运行。我是按照其他模块的实现方式来添加GridText的,并且单独在环境链接中测试API时,响应是正常的。

以下是相关代码和完整错误信息:

[slug].tsx

import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { GraphQLClient, gql } from "graphql-request";
import NotFound from "./NotFound";
import "../styles/index.css";
import Nav from "../modules/Nav/index";
import { navigationQuery, NavigationResponse } from "../modules/Nav/fragment";
import Footer from "../modules/Footer/index";
import { footerQuery, FooterResponse } from "../modules/Footer/fragment";
import TextImage from "../modules/TextImage/index";
import {
  TEXT_IMAGE_FRAGMENT,
  TextImageFields,
} from "../modules/TextImage/fragment";
import Hero from "../modules/Hero/index";
import { HERO_FRAGMENT, HeroFields } from "../modules/Hero/fragment";
import GridTour from "../modules/GridTour/index";
import {
  GRID_TOUR_FRAGMENT,
  GridTourFields,
} from "../modules/GridTour/fragment";
import GridText from "../modules/GridText/index";
import {
  GRID_TEXT_FRAGMENT,
  GridTextFields,
} from "../modules/GridText/fragment";

// 定义页面数据结构
interface PageData {
  title: string;
  modules: Array<
    {
      identifier: string;
    } & (TextImageFields | HeroFields | GridTourFields | GridTextFields)
  >;
}

// 定义GraphQL响应的预期结构
interface GraphQLResponse {
  page: PageData;
}

// 使用Vite环境变量初始化GraphQL客户端
const graphConnect = new GraphQLClient(import.meta.env.VITE_ENDPOINT);

// 根据slug获取页面数据的GraphQL查询
const pageQuery = gql`
  query ($slug: String!) {
    page(where: { slug: $slug }) {
      title
      modules {
          ...TextImageFields
          ...HeroFields
          ...GridTourFields
          ...GridTextFields
        }
      }
    }
  }
  ${TEXT_IMAGE_FRAGMENT}
  ${HERO_FRAGMENT}
  ${GRID_TOUR_FRAGMENT}
  ${GRID_TEXT_FRAGMENT}
`;

const Page: React.FC = () => {
  const { slug } = useParams<{ slug: string }>(); // 从URL参数获取slug
  const [pageData, setPageData] = useState<PageData | null>(null); // 存储页面数据的状态
  const [navigationData, setNavigationData] = useState<NavigationResponse | null>(null); // 导航数据状态
  const [footerData, setFooterData] = useState<FooterResponse | null>(null); // 页脚数据状态
  const [loading, setLoading] = useState(true); // 加载状态
  const [error, setError] = useState<string | null>(null); // 错误状态

  useEffect(() => {
    const fetchData = async () => {
      setLoading(true); // 开始加载
      setError(null); // 重置错误状态

      try {
        // 获取页面数据
        const response = await graphConnect.request<GraphQLResponse>(
          pageQuery,
          {
            slug,
          }
        );

        if (!response.page) {
          throw new Error(`未找到slug为${slug}的页面`);
        }

        setPageData(response.page); // 设置页面数据

        // 获取导航数据
        const navigationResponse = await graphConnect.request<NavigationResponse>(navigationQuery);
        setNavigationData(navigationResponse);

        // 获取页脚数据
        const footerResponse = await graphConnect.request<FooterResponse>(
          footerQuery
        );
        setFooterData(footerResponse);
      } catch (err: any) {
        // 如果有GraphQL特定错误响应则打印详情
        if (err.response && err.response.errors) {
          console.error("GraphQL响应错误详情:", err.response.errors);
        } else {
          console.error("意外错误:", err);
        }

        setError("加载数据失败"); // 设置错误提示
      } finally {
        setLoading(false); // 结束加载
      }
    };

    fetchData();
  }, [slug]); // 当slug变化时重新执行

  if (loading) {
    return <div>加载中...</div>; // 显示加载状态
  }

  if (error) {
    return <div>{error}</div>; // 显示错误信息
  }

  if (!pageData) {
    return <NotFound />; // 展示404页面
  }

  return (
    <>
      {navigationData && <Nav data={navigationData.navigation} />}

      <div className="relative top-16">
        {pageData.modules.map((module) => {
          if (!module.id) {
            return null;
          }
          switch (module.identifier) {
            case "TextImage":
              return (
                <TextImage key={module.id} data={module as TextImageFields} />
              );
            case "Hero":
              return <Hero key={module.id} data={module as HeroFields} />;
            case "GridTour":
              return (
                <GridTour key={module.id} data={module as GridTourFields} />
              );
            case "GridText":
              return (
                <GridText key={module.id} data={module as GridTextFields} />
              );
            default:
              return null;
          }
        })}
      </div>

      {footerData && <Footer data={footerData.footer} />}
    </>
  );
};

export default Page;

GridText/index.tsx

import React from "react";

interface HeadlineData {
  size: string;
  text: string;
}

interface GridTextProps {
  data: {
    headline?: HeadlineData | null;
  };
}

const GridText: React.FC<GridTextProps> = ({ data }) => {
  return (
    <div>
      <p>{data?.headline?.text}</p>
    </div>
  );
};

export default GridText;

GridText/fragment.ts

import { gql } from "graphql-request";

export const GRID_TEXT_FRAGMENT = gql`
  fragment GridTextFields on GridText {
    id
    identifier
    headline {
      size
      text
    }
  }
`;

export interface GridTextFields {
  id: string;
  identifier: string;
  headline: {
    size: string;
    text: string;
  } | null;
}

完整错误信息

Error fetching data: _ClientError: GraphQL Error (Code: 400): {"response":{"status":400,"headers":{}},"request":{"query":"
  query ($slug: String!) {
    page(where: { slug: $slug }) {
      title
      modules {
        ... on TextImage {
          ...TextImageFields
        }
        ... on Hero {
          ...HeroFields
        }
        ... on GridTour {
          ...GridTourFields
        }
        ... on GridText {
          ...GridTextFields
        }
      }
    }
  }
  
  fragment TextImageFields on TextImage {
    id
    identifier
    headline
    image {
      url
      alt
    }
    paragraph {
      text {
        html
      }
    }
  }

  
  fragment HeroFields on Hero {
    id
    identifier
    imageLarge {
      url
      alt
    }
    links {
      ...PagelinkFields
      ...URLFields
    }
    paragraph {
      text {
        html
      }
    }
    imageSmall {
      url
      alt
    }
    headline {
      size
      text
    }
  }
  
  fragment PagelinkFields on Pagelink {
    identifier
    id
    text
    page {
      slug
    }
  }

  
  fragment URLFields on URL {
    identifier
    id
    url
    text
  }


  
  fragment GridTourFields on GridTour {
    id
    identifier
    headline {
      size
      text
    }
    gridTourSection {
      id
      headline
      guidedTour {
        slug
        id
        bookingForm
        coverImage {
          url
          alt
        }
        description
        distance
        duration
        highlights
        images {
          id
          url
          alt
          width
          height
        }
        title
      }
    }
  }

  
  fragment GridTextFields on GridText {
    id
    identifier
    headline {
      size
      text
    }
  }

","variables":{"slug":"home"}}}
at runRequest (graphql-request.js?v=51386c9c:7767:12)
at async GraphQLClient.request (graphql-request.js?v=51386c9c:7962:22)
at async fetchData ([slug].tsx:91:26)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:20:58