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

React调用.NET 8 Minimal API后端时出现重复请求与JSON解析错误的问题排查求助

React调用.NET 8 Minimal API后端时出现重复请求与JSON解析错误的问题排查求助

我正在开发一个项目,后端是.NET 8的Minimal API,前端是用VS2022自带模板生成的React应用。作为React新手,可能犯了一些入门错误,还请大家帮忙看看。

目前我遇到两个棘手的问题:

  • React前端会发送重复请求,App组件甚至渲染了6次,这看起来不太正常,感觉是配置哪里出了问题
  • 每个HTTP请求的响应都出现JSON解析错误,但我用Swagger测试后端接口时,返回的都是格式完全正确的JSON

以下是我的App组件代码:

import { useEffect, useState } from 'react';

import './App.css';

import TreeView from './components/TreeView';

interface DetailedPart {
  id: number;
  guid: string;
  parentName: string;
  componentName: string;
  partNumber: string;
  title: string;
  quantity: number;
  type: string;
  item: string;
  material: string;
}

export interface Node {
  id: number,
  guid: string,
  name: string,
  children: Node[],
  isExpanded?: boolean,
  isHighlighted?: boolean,
}

function App() {
  console.log('App rendered');
  const [detparts, setDetparts] = useState<DetailedPart[]>([]);
  const [tree, setTree] = useState<Node[]>([]);

  useEffect(() => {
    console.log('useEffect called');
    populateParts();
    populateTree();
  }, []);

  const dataGrid = detparts === undefined
    ? <p><em>Loading... Please refresh once the ASP.NET backend has started. See https://aka.ms/jspsintegrationreact for more details.</em></p>
    : <table className="table table-striped" aria-labelledby="tabelLabel">
        <thead>
          <tr>
            <th>PARENTNAME</th>
            <th>COMPONENTNAME</th>
            <th>PARTNUMBER</th>
            <th>TITLE</th>
            <th>QUANTITY</th>
            <th>TYPE</th>
            <th>ITEM</th>
            <th>MATERIAL</th>
          </tr>
        </thead>
        <tbody>
          {detparts.map(part =>
            <tr key={part.guid}>
              <td>{part.parentName}</td>
              <td>{part.componentName}</td>
              <td>{part.partNumber}</td>
              <td>{part.title}</td>
              <td>{part.quantity}</td>
              <td>{part.type}</td>
              <td>{part.item}</td>
              <td>{part.material}</td>
            </tr>
          )}
        </tbody>
      </table>;

  return (
    <div className="container" style={{ display: 'flex', height: '100vh' }}>
      <div style={{ width: '33%', overflow: 'auto', outline: '1px solid black', outlineColor: 'red' }}>
        <TreeView data={tree} />
      </div>
      <div style={{ flex: 1 }}>
        <h1 id="tabelLabel">QBuild</h1>
        <p>This component demonstrates fetching data from the server.</p>
        {dataGrid}
      </div>
    </div>
  );

  function populateParts() {
    console.log('populateParts called');
    fetch('detparts')
      .then(response => response.json())
      .then(data => {
        try {
          const jsonData = JSON.parse(data);
          setDetparts(jsonData);
        } catch (e) {
          console.error('Error parsing JSON:', e);
        }
      })
      .catch(error => {
        console.error('Error fetching parts:', error);
      });
  };

  function populateTree() {
    console.log('populateTree called');
    fetch('tree')
      .then(response => response.text()) // Read response as text
      .then(data => {
        try {
          const jsonData = JSON.parse(data); // Parse the response as JSON
          setTree(jsonData);
        } catch (error) {
          console.error('Error parsing JSON:', error);
        }
      })
      .catch(error => {
        console.error('Error fetching tree:', error);
      });
  };
}

export default App;

另外,我也附上Vite的配置文件vite.config.ts,供大家参考:

import { fileURLToPath, URL } from 'node:url';

import { defineConfig } from 'vite';
import plugin from '@vitejs/plugin-react';

import fs from 'fs';
import path from 'path';
import child_process from 'child_process';

const baseFolder =
  process.env.APPDATA !== undefined && process.env.APPDATA !== ''
    ? `${process.env.APPDATA}/ASP.NET/https`
    : `${process.env.HOME}/.aspnet/https`;

const certificateArg = process.argv.map(arg => arg.match(/--name=(?<value>.+)/i)).filter(Boolean)[0];
const certificateName = certificateArg ? certificateArg.groups.value : "qbuild.client";

if (!certificateName) {
  console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<<app>> explicitly.')
  process.exit(-1);
}

const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);

if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) {
  if (0 !== child_process.spawnSync('dotnet', [
    'dev-certs',
    'https',
    '--export-path',
    certFilePath,
    '--format',
    'Pem',
    '--no-password',
  ], { stdio: 'inherit', }).status) {
    throw new Error("Could not create certificate.");
  }
}

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [plugin()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  server: {
    proxy: {
      '^/detparts': {
        target: 'https://localhost:7272/',
        secure: false
      },
      '^/tree': {
        target: 'https://localhost:7272/',
        secure: false
      }
    },
    port: 5175,
    https: {
      key: fs.readFileSync(keyFilePath),
      cert: fs.readFileSync(certFilePath),
    }
  }
})

我知道状态变化会触发重新渲染,但6次渲染和重复请求实在不太正常。另外,Swagger返回的JSON明明是正常的,为什么前端会出现解析错误呢?会不会是CORS配置的问题?希望大家能帮我找出问题所在,谢谢!

备注:内容来源于stack exchange,提问作者GUZZ

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 06:20:31