javascriptreactjsmiragejs

MirageJs does not throw status 400


I am new to react and I'm working on react fetch using useEffect. Im using miragejs to mimic an api server. I am testing the sad path and have made the miragejs API to return a 400 status code.

im using miragejs to mimic an api server.

here is the 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) => {
        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) => {
        // Hard-code the hostId for now
        return schema.vans.where({ hostId: "123" })
    })

    this.get("/host/vans/:id", (schema, request) => {
        // Hard-code the hostId for now
        const id = request.params.id
        return schema.vans.findBy({ id, hostId: "123" })
    })
}
})

The api.js is :

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
}

below is my fetch code:

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
}

I'm using this in my component to set some states.

I'm using a try-catch block while calling this API inside the use effect. But I see that the error is not caught.

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()
}, [])

I see it proceeds and breaks with runtime errors.

Somehow the response is 200 even I'm returning 400 in server.js. enter image description here

I get the error on /vans path. the file is Vans.jsx

enter image description here

Vans.jsx is :

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>
  )
}

Please advise.


Solution

  • The issue was with the import in server.js. Response was not imported

    with import { createServer, Model, Response } from "miragejs" its working fine.