RTK Query未使用配置的baseUrl,请求错误指向localhost:3000
问题:RTK Query未使用配置的baseUrl,请求本地开发服务器地址
问题现象
通过Components/Pages/Scrap.tsx打印出以下错误:
{status: 'PARSING_ERROR', originalStatus: 200, data: '<!DOCTYPE html>\n<html lang="en">\n <head>\n <met…uild` or `yarn build`.\n -->\n </body>\n</html>\n', error: `SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON`} data: "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <link rel=\"icon\" href=\"/favicon.ico\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <meta name=\"theme-color\" content=\"#000000\" />\n <meta\n name=\"description\"\n content=\"Web site created using create-react-app\"\n />\n <link rel=\"apple-touch-icon\" href=\"/logo192.png\" />\n <!--\n manifest.json provides metadata used when your web app is installed on a\n user's mobile device or desktop.\n -->\n <link rel=\"manifest\" href=\"/manifest.json\" />\n <!--\n Notice the use of in the tags above.\n It will be replaced with the URL of the `public` folder during the build.\n Only files inside the `public` folder can be referenced from the HTML.\n\n Unlike \"/favicon.ico\" or \"favicon.ico\", \"/favicon.ico\" will\n work correctly both with client-side routing and a non-root public URL.\n Learn how to configure a non-root public URL by running `npm run build`.\n -->\n <title>React App</title>\n <script defer src=\"/static/js/bundle.js\"></script></head>\n <body>\n <noscript>You need to enable JavaScript to run this app.</noscript>\n <div id=\"root\"></div>\n <!--\n This HTML file is a template.\n If you open it directly in the browser, you will see an empty page.\n\n You can add webfonts, meta tags, or analytics to this file.\n The build step will place the bundled scripts into the <body> tag.\n\n To begin the development, run `npm start` or `yarn start`.\n To create a production bundle, use `npm run build` or `yarn build`.\n -->\n </body>\n</html>\n" error: "SyntaxError: Unexpected token '<', \"<!DOCTYPE \"... is not valid JSON" originalStatus: 200 status: "PARSING_ERROR" [[Prototype]]: Object
经开发者工具网络面板排查发现,RTK Query实际请求的地址为http://localhost:3000/scrape?url=https://somewebsite.com,而非预期的https://localhost:7125/scrape?url=https://somewebsite.com。
相关代码
api/scrape-api.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import type { scrapeModel } from '../models/scrape-model'; export const scrapeApi = createApi({ reducerPath: 'scrapeApi', baseQuery: fetchBaseQuery({ baseUrl: 'https://localhost:7125/' }), endpoints: builder => ({ scrapeUrl: builder.query<scrapeModel, string>({ query: url => `scrape?url=${url}` }) }) }); export const { useScrapeUrlQuery } = scrapeApi;
store/index.ts
import { configureStore } from '@reduxjs/toolkit'; import { setupListeners } from '@reduxjs/toolkit/dist/query'; import { scrapeApi } from '../api/scrape-api'; import scrapeReducer from './scrape'; export const store = configureStore({ reducer: { [scrapeApi.reducerPath]: scrapeApi.reducer, scrape: scrapeReducer }, middleware: getDefaultMiddleware => { return getDefaultMiddleware().concat(scrapeApi.middleware); } }); setupListeners(store.dispatch); export type RootState = ReturnType<typeof store.getState>;
Components/Pages/Scrap.tsx
import { useEffect } from 'react'; import { useScrapeUrlQuery } from '../../api/scrape-api'; const Scrape = () => { const { data, error, isLoading } = useScrapeUrlQuery( 'https://somewebsite.com' ); useEffect(() => { if (error) { console.log(error); } }, [data, error, isLoading]); return ( <div> <h1>I'm the scrape page</h1> {isLoading && <div>Loading...</div>} </div> ); }; export default Scrape;
解答
问题原因
核心原因是跨域请求被浏览器拦截,或开发环境代理配置错误:
- 浏览器的同源策略会阻止前端直接请求不同域名/端口的后端服务,此时如果没有正确配置CORS,请求会被拦截,转而可能被本地开发服务器(如Create React App的localhost:3000)接收,返回React的index.html页面,导致JSON解析错误。
- 如果项目配置了代理但规则错误,也会把请求转发到本地服务器,而非目标后端地址。
解决方法
方法1:配置后端CORS(通用方案)
在运行于https://localhost:7125的后端服务中,添加CORS配置,允许来自http://localhost:3000的请求:
- Node.js/Express:使用
cors中间件,设置origin: "http://localhost:3000" - .NET:在
Program.cs中配置builder.Services.AddCors(options => options.AddPolicy("AllowLocal", policy => policy.WithOrigins("http://localhost:3000").AllowAnyMethod().AllowAnyHeader()))
方法2:使用Create React App代理(开发环境推荐)
在项目根目录的package.json中添加代理配置:
{ "proxy": "https://localhost:7125" }
然后修改scrape-api.ts的baseUrl为相对路径:
baseQuery: fetchBaseQuery({ baseUrl: '/' }),
开发环境下,请求会自动转发到目标后端,同时规避跨域问题。
方法3:直接使用绝对路径并确保CORS正常
若不想用代理,需确保:
- 后端服务
https://localhost:7125正常运行,/scrape接口能返回合法JSON - 后端已正确配置CORS,允许
http://localhost:3000的请求 - 检查
baseUrl拼写无误,无斜杠遗漏或格式错误
额外注意点
- 生产环境不要使用Create React App的代理配置,建议将前后端部署在同一域名下,或用Nginx等反向代理处理跨域。
- 使用
fetchBaseQuery的绝对路径baseUrl时,必须确保后端允许跨域,否则浏览器会拦截请求。
内容的提问来源于stack exchange,提问作者Jason Braswell
相关产品推荐
相关产品推荐

