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
相关产品推荐
相关产品推荐

