MirageJS未返回400状态码导致React useEffect中try-catch无法捕获错误的问题求助
MirageJS未返回400状态码导致React useEffect中try-catch无法捕获错误的问题求助
大家好,我是React新手,目前正在用useEffect实现数据获取功能,同时用MirageJS模拟API服务器。现在我想测试错误场景,特意在MirageJS的API配置里设置返回400状态码,但遇到了奇怪的问题:
明明在server.js里指定了返回400,可实际请求却拿到了200状态码,导致我在useEffect里用try-catch包裹的API调用根本捕获不到错误,程序直接抛出运行时错误。
下面是我的相关代码,麻烦大家帮忙看看哪里出问题了:
1. MirageJS的server.js配置
import { createServer, Model } from "miragejs" createServer({ models: { vans: Model, }, seeds(server) { server.create("van", { id: "1", name: "Modest Explorer", price: 60, description: "The Modest Explorer is a van designed to get you out of the house and into nature. This beauty is equipped with solar panels, a composting toilet, a water tank and kitchenette. The idea is that you can pack up your home and escape for a weekend or even longer!", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/modest-explorer.png", type: "simple", hostId: "123" }) server.create("van", { id: "2", name: "Beach Bum", price: 80, description: "Beach Bum is a van inspired by surfers and travelers. It was created to be a portable home away from home, but with some cool features in it you won't find in an ordinary camper.", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/beach-bum.png", type: "rugged", hostId: "123" }) server.create("van", { id: "3", name: "Reliable Red", price: 100, description: "Reliable Red is a van that was made for travelling. The inside is comfortable and cozy, with plenty of space to stretch out in. There's a small kitchen, so you can cook if you need to. You'll feel like home as soon as you step out of it.", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/reliable-red.png", type: "luxury", hostId: "456" }) server.create("van", { id: "4", name: "Dreamfinder", price: 65, description: "Dreamfinder is the perfect van to travel in and experience. With a ceiling height of 2.1m, you can stand up in this van and there is great head room. The floor is a beautiful glass-reinforced plastic (GRP) which is easy to clean and very hard wearing. A large rear window and large side windows make it really light inside and keep it well ventilated.", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/dreamfinder.png", type: "simple", hostId: "789" }) server.create("van", { id: "5", name: "The Cruiser", price: 120, description: "The Cruiser is a van for those who love to travel in comfort and luxury. With its many windows, spacious interior and ample storage space, the Cruiser offers a beautiful view wherever you go.", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/the-cruiser.png", type: "luxury", hostId: "789" }) server.create("van", { id: "6", name: "Green Wonder", price: 70, description: "With this van, you can take your travel life to the next level. The Green Wonder is a sustainable vehicle that's perfect for people who are looking for a stylish, eco-friendly mode of transport that can go anywhere.", imageUrl: "https://assets.scrimba.com/advanced-react/react-router/green-wonder.png", type: "rugged", hostId: "123" }) }, routes() { this.namespace = "api" this.logging = false this.get("/vans", (schema, request) => { // 这里设置返回400错误,但实际请求得到200 return new Response(400, {}, {error: "Error fetching data"}) // return schema.vans.all() }) this.get("/vans/:id", (schema, request) => { const id = request.params.id return schema.vans.find(id) }) this.get("/host/vans", (schema, request) => { // 暂时硬编码hostId return schema.vans.where({ hostId: "123" }) }) this.get("/host/vans/:id", (schema, request) => { // 暂时硬编码hostId const id = request.params.id return schema.vans.findBy({ id, hostId: "123" }) }) } })
2. api.js的请求封装函数
export async function getVans() { const res = await fetch("/api/vans") if (!res.ok) { throw Object.assign(new Error("Failed to fetch vans"),{ message: "Failed to fetch vans", statusText: res.statusText, status: res.status }); } const data = await res.json() return data.vans }
3. Vans.jsx组件中的useEffect调用逻辑
import React from "react"; import { useState, useEffect } from "react"; import { Link, useSearchParams } from "react-router-dom"; import { getVans } from "../../api"; export default function Vans() { const [vans, setVans] = useState([]) const [searchParams, setSearchParams] = useSearchParams(); const [loading,setLoading] = useState(false); const [error, setError] = useState(null); const typeFilter = searchParams.get("type"); useEffect(() => { async function loadVans() { setLoading(true) try { const data = await getVans() console.log("fetched data: "+data); setVans(data) } catch (err) { console.log("error :"+err) setError(err) } finally { setLoading(false) } } loadVans() }, []) const displayedVans = typeFilter ? vans.filter(van => van.type === typeFilter) : vans console.log("typeFilter :" + typeFilter); const vanElements = displayedVans.map(van => { return ( <div key={van.id} className="van-tile"> <Link to={van.id} state={{ search: `?${searchParams.toString()}`, type: typeFilter }}> <img src={van.imageUrl} alt={van.name} /> <div className="van-info"> <h3>{van.name}</h3> <p>${van.price}<span>/day</span></p> </div> <i className={`van-type ${van.type} selected`}>{van.type}</i> </Link> </div> ) }) function handleFilterChange(key, value) { setSearchParams(prevParams => { if (value === null) { prevParams.delete(key) } else { prevParams.set(key, value) } return prevParams }) } if(loading){ return(<h1>Loading</h1>) } if (error) { return <h1>There was an error: {error.message}</h1> } return ( <div className="van-list-container"> <h1>Explore our van options</h1> <div className="van-list-filter-buttons"> <button onClick={() => handleFilterChange("type", "simple")} className={ `van-type simple ${typeFilter === "simple" ? "selected" : ""}` } >Simple</button> <button onClick={() => handleFilterChange("type", "luxury")} className={ `van-type luxury ${typeFilter === "luxury" ? "selected" : ""}` } >Luxury</button> <button onClick={() => handleFilterChange("type", "rugged")} className={ `van-type rugged ${typeFilter === "rugged" ? "selected" : ""}` } >Rugged</button> {typeFilter ? (<button onClick={() => setSearchParams({})} className="van-type clear-filters">Clear Filters</button>) : null} </div> <div className="van-list"> {vanElements} </div> </div> ) }
现在的核心问题是:我明明在MirageJS里配置了/api/vans接口返回400状态码,但实际请求时却拿到200,导致getVans函数里的!res.ok判断不触发,错误无法被try-catch捕获,程序直接报错。麻烦大家帮我排查一下问题根源,谢谢!
备注:内容来源于stack exchange,提问作者manjosh
相关产品推荐
相关产品推荐

