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

React JS连接DB API时net::ERR_CONNECTION_REFUSED错误的解决方法

React JS: DB API连接错误

我尝试连接DB API,但无法解决以下错误:

  • courseApi.js:10 GET http://localhost:3001/courses/ net::ERR_CONNECTION_REFUSED
  • react_devtools_backend_compact.js:2367 API调用失败。TypeError: Failed to fetch
  • 未捕获的(Promise中)TypeError: Failed to fetch
    at getCourses (courseApi.js:10:1)
    at CoursesPage.js:9:1

App.js

import React from "react";
import HomePage from "./HomePage";
import CoursesPage from "./CoursesPage";
// import CourseForm from "./CourseForm";
import AboutPage from "./AboutPage";
import Header from "./common/Header";
import { Route, Switch, Redirect } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import NotFoundPage from "./NotFoundPage";
import ManageCoursePage from "./ManageCoursePage";

function App() {
  return (
    <div className="container-fluid">
      <ToastContainer
        autoClose={3000} 
        hideProgressBar
      />
      <Header />
      <Switch>
        <Route path="/" exact component={HomePage} />
        <Route path="/courses" component={CoursesPage} />
        <Route path="/course" component={ManageCoursePage} />
        <Route path="/course/:slug" component={ManageCoursePage} />
        <Route path="/about" component={AboutPage} />
        <Route component={NotFoundPage} />
        <Redirect from="/about-page" to="/about" />
      </Switch>
    </div>
  );
}

export default App;

index.js

import "bootstrap/dist/css/bootstrap.min.css";
import React from "react";
// import ReactDOM from "react-dom";
import { BrowserRouter as Router } from "react-router-dom";

import App from "./components/App";
import * as ReactDOM from "react-dom/client";
const root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
  <Router>
    <App />
  </Router>
);

CoursesPage.js

import React, { useState, useEffect } from "react";
import { getCourses } from "../api/courseApi";
import CourseList from "./CourseList";

function CoursesPage() {
  const [courses, setCourses] = useState([]);

  useEffect(() => {
    getCourses().then((_courses) => setCourses(_courses));
  }); 

  return (
    <>
      <div className="container-fluid">
        <h1>Course Page</h1>
        <a className="btn btn-primary" href="/course">
          Add course
        </a>
        <CourseList courses={courses} />
      </div>
    </>
  );
}

export default CoursesPage;

courseApi.js

import { handleResponse, handleError } from "./apiUtils";
const baseUrl = process.env.REACT_APP_API_URL + "/courses/";

export function getCourses() {
  console.log(baseUrl);
  // console.log(handleResponse);
  // console.log(handleError);
  // debugger;
  console.log(window.location.href);
  return fetch(baseUrl).then(handleResponse).catch(handl`your text`eError);
}

export function getCourseBySlug(slug) {
  return fetch(baseUrl + "?slug=" + slug)
    .then((response) => {
      if (!response.ok) throw new Error("Network response was not ok.");
      return response.json().then((courses) => {
        if (courses.length !== 1) throw new Error("Course not found: " + slug);
        return courses[0]; // should only find one course for a given slug, so return it.
      });
    })
    .catch(handleError);
}

export function saveCourse(course) {
  return fetch(baseUrl + (course.id || ""), {
    method: course.id ? "PUT" : "POST", // POST for create, PUT to update when id already exists.
    headers: { "content-type": "application/json" },
    body: JSON.stringify({
      ...course,
      // Parse authorId to a number (in case it was sent as a string).
      authorId: parseInt(course.authorId, 10),
    }),
  })
    .then(handleResponse)
    .catch(handleError);
}

export function deleteCourse(courseId) {
  return fetch(baseUrl + courseId, { method: "DELETE" })
    .then(handleResponse)
    .catch(handleError);
}

apiUtils.js

export async function handleResponse(response) {
  if (response.ok) return response.json();
  if (response.status === 400) {
    // So, a server-side validation error occurred.
    // Server side validation returns a string error message, so parse as text instead of json.
    const error = await response.text();
    throw new Error(error);
  }
  throw new Error("Network response was not ok.");
}

// In a real app, would likely call an error logging service.
export function handleError(error) {
  // eslint-disable-next-line no-console
  console.error("API call failed. " + error);
  throw error;
}

package.json

...
"scripts": {
   "start": "run-p start:dev start:api",
   "start:dev": "cross-env REACT_APP_API_URL=http://localhost:3001 react-scripts start",
   "prestart:api": "node tools/createMockDb.js",
  ...
 }
}
...

问题排查与修复方案

1. 核心错误原因

ERR_CONNECTION_REFUSED说明localhost:3001端口的API服务根本没启动,加上代码里的拼写错误,导致双重问题。

2. 分步修复

(1)修正courseApi.js的拼写错误

把getCourses函数里的catch(handlyour texteError)改成catch(handleError),这是明显的输入失误。

(2)完善API服务启动脚本

你的package.json里只有prestart:api(生成mock数据),但缺少start:api来启动API服务。假设用json-server做mock API:

  • 先安装依赖:npm install json-server --save-dev
  • 然后修改package.json的scripts:
    "scripts": {
      "start": "run-p start:dev start:api",
      "start:dev": "cross-env REACT_APP_API_URL=http://localhost:3001 react-scripts start",
      "start:api": "json-server --port 3001 --watch tools/db.json",
      "prestart:api": "node tools/createMockDb.js",
      ...
    }
    

(3)优化useEffect执行逻辑

CoursesPage.js里的useEffect没有依赖数组,会导致组件每次渲染都重复调用API,改成:

useEffect(() => {
  getCourses().then((_courses) => setCourses(_courses));
}, []); // 空数组表示仅在组件挂载时执行一次

(4)验证API服务是否正常

重启项目npm start后,直接在浏览器访问http://localhost:3001/courses,如果能返回JSON数据,说明API服务正常,前端就能拿到数据了。

内容的提问来源于stack exchange,提问作者J. Nam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 07:39:58