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

React重构抽离GraphQL查询触发Bad Request报错排查与代码优化

问题成因排查
  • 优先检查导入路径拼写:你当前写的导入路径是../../utls/queries,文件夹名utls存在明显拼写错误(常规工具文件夹命名为utils)。如果本地同时存在拼写错误的旧utls文件夹、且里面存了语法错误的旧版查询语句,构建缓存可能导致你导入的是错误文件里的内容,即使你后续修改了正确路径下的查询语句也不会生效。
  • 排查不可见字符问题:如果查询语句是从其他地方复制粘贴到独立文件的,很可能带上零宽空格、UTF-8 BOM头等控制台打印不可见的特殊字符,这类字符不会影响===的相等判断,但会导致GraphQL服务解析查询语法失败返回400。直接打开浏览器开发者工具的Network面板,对比内联query请求和导入productQuery请求的Request Payload,就能直接看到内容差异。
  • 检查手滑传参错误:你代码里写了一行完全未使用的const newQuer = { ...productQuery },如果替换参数时误将请求体里的query字段传成newQuer,相当于把字符串展开成了类数组对象传给服务端,GraphQL接收到非字符串格式的查询内容会直接返回400错误。
代码精简优化方案
  • 移除冗余代码:删掉未使用的newQuer变量,合并重复的组件导入语句,去掉不必要的DOM嵌套层级。
  • 简化类组件写法:直接用类属性声明state,省去冗余的constructor构造函数;把数据请求逻辑抽成独立类方法,和生命周期逻辑解耦。
  • 优化渲染逻辑:提前过滤出匹配当前路由的分类数据,避免遍历全部分类时返回空字符串造成的冗余节点;用商品自身的id作为列表key,替代不稳定的数组index;简化分类名首字母大写的重复逻辑。
  • 补全基础容错:添加请求错误处理,避免接口报错时页面一直loading或者直接崩溃。

优化后的完整代码参考:

import React, { Component } from 'react';
import { Loader, ProductCard } from '../../components';
import './ProductListing.scss';
// 注意修正路径拼写
import { productQuery } from '../../utils/queries';

export class ProductListing extends Component {
  // 直接用类属性声明state,省去constructor
  state = {
    loading: true,
    products: [],
    categoryId: '',
    error: null
  };

  componentDidMount() {
    const categoryId = window.location.pathname.replace('/', '');
    this.setState({ categoryId });
    this.fetchProducts();
  }

  // 抽离请求逻辑为独立方法,用async/await简化Promise链
  async fetchProducts() {
    try {
      const res = await fetch('http://localhost:4000', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Accept: 'application/json',
        },
        body: JSON.stringify({ query: productQuery })
      });
      const { data } = await res.json();
      this.setState({
        products: data,
        loading: false
      });
    } catch (err) {
      this.setState({ error: err, loading: false });
    }
  }

  render() {
    const { loading, categoryId, products, error } = this.state;
    
    if (loading) return <Loader />;
    if (error) return <div>商品加载失败,请刷新重试</div>;

    // 提前匹配当前分类,避免渲染冗余空节点
    const currentCategory = products.categories.find(item => item.name === categoryId);
    const formatCategoryName = categoryId[0].toUpperCase() + categoryId.substring(1);

    return (
      <div>
        <h2 className='page__listing__title'>{formatCategoryName}</h2>
        <div className='productlisting__page'>
          {currentCategory && (
            <div className='product__listing__card'>
              {currentCategory.products.map(product => (
                <ProductCard product={product} key={product.id} />
              ))}
            </div>
          )}
        </div>
      </div>
    );
  }
}

export default ProductListing;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 23:01:10