Accelerate React Development Using MSW

Dharshan kDharshan k
5 min read

This blog provides a step-by-step instructions to add msw into your react app. Alright, lets jump on!

Bootstrapping application

Lets use Vite to setup our react app as it is the go to way of creating a react application as of today. Run the following command in your favorite terminal to get started. Follow the onscreen instructions. I am choosing to use React with TypeScript + SWC here.

npm create vite@latest

Setting up msw

Installing msw

npm install msw@latest --save-dev

Setup mock endpoints

Create a folder called mock/api with a new file called handler.ts

// /src/mock/api/handler.ts
import { http, HttpResponse } from "msw";
import { blogs } from "../data/blogs";

export const handlers = [
  http.get("/api/blogs", () => {
    return HttpResponse.json({ blogs });
  }),
  http.get("/api/blogs/:id", ({ params }) => {
    const blog = blogs.find((b) => b.id === params.id);
    if (blog) {
      return HttpResponse.json(blog, { status: 200 });
    } else {
      return HttpResponse.json({ message: "Blog not found" }, { status: 404 });
    }
  })
];

Blog data

Create a folder called data under the mock folder we created earlier. Create a file called blog.data.ts under it.

// /src/mock/data/blogs.data.ts
import { Blog } from "../../types";

export const blogs: Blog[] = [
  {
    id: "1",
    title: "Exploring the Beauty of Nature",
    category: "Travel",
    description: "A journey through the most breathtaking landscapes on Earth.",
    content:
      "Traveling allows us to explore the beauty of nature. From the majestic mountains of the Himalayas to the serene beaches of the Maldives, nature offers us a wide range of breathtaking landscapes. Walking through dense forests, we encounter a variety of flora and fauna. The sight of a clear blue sky merging with the horizon of a vast ocean is simply mesmerizing. Whether it's the silence of a desert or the vibrant colors of a coral reef, each place has its unique charm. Nature not only soothes our eyes but also rejuvenates our soul. Embracing nature helps us understand the importance of preserving our environment for future generations."
  },
  {
    id: "2",
    title: "The Future of Technology",
    category: "Technology",
    description:
      "An insight into the emerging trends and innovations in technology.",
    content:
      "Technology is evolving at an unprecedented pace, transforming our lives in ways we never imagined. From artificial intelligence to blockchain, the future of technology holds immense possibilities. AI is set to revolutionize industries by automating tasks and providing insights through data analysis. Blockchain technology promises to enhance security and transparency across various sectors. The advent of 5G will enable faster and more reliable internet connections, paving the way for advancements in IoT and smart cities. Quantum computing, though in its nascent stages, has the potential to solve complex problems at unimaginable speeds. As we embrace these innovations, ethical considerations and digital literacy become crucial to ensure technology serves humanity positively."
  },
  {
    id: "3",
    title: "Healthy Eating: A Guide to Nutrition",
    category: "Health",
    description:
      "Tips and advice on how to maintain a balanced and nutritious diet.",
    content:
      "Healthy eating is essential for maintaining overall well-being. A balanced diet provides our bodies with the necessary nutrients to function properly. Incorporating a variety of fruits and vegetables ensures we get a range of vitamins and minerals. Whole grains, such as brown rice and quinoa, are excellent sources of fiber and help in digestion. Lean proteins like chicken, fish, and legumes are crucial for muscle repair and growth. It's important to stay hydrated by drinking plenty of water throughout the day. Reducing the intake of processed foods and sugars can prevent health issues like obesity and diabetes. By making mindful food choices, we can enhance our energy levels, improve mental clarity, and boost our immune system."
  }
];

Generating service worker

Let's generate the service worker which is the one that's actually going to intercept the XHR calls and return the response that we define.

npx msw init ./public --save

Adding the service worker

Create a file called browser.ts under the mock folder

// /src/mock/browser.ts
import { setupWorker } from "msw/browser";
import { handlers } from "./api/handler.js";

export const worker = setupWorker(...handlers);

Starting service worker

Start the mock service worker along with rendering the app so that it can start intercepting the XHR calls.

// src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import { setupWorker } from "msw/browser";
import { handlers } from "./mock/api/handler.ts";
import "./index.css";

const enableMocking = async (): Promise<void> => {
  if (import.meta.env.DEV) {
    const { worker } = await import('./mock/browser.ts')
    await worker.start()
  }
}

enableMocking().then(() => {
  ReactDOM.createRoot(document.getElementById("root")!).render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
});

Making API call

Let's make an API call using axios to our endpoint to fetch our blogs and display their titles.

// /src/App.tsx

import { useEffect, useState } from "react";
import reactLogo from "./assets/react.svg";
import viteLogo from "/vite.svg";
import axios from "axios";
import { Blog } from "./types";
import "./App.css";

function App() {
  const [blogs, setBlogs] = useState<Blog[]>([]);

  useEffect(() => {
    (async () => {
      const { data } = await axios.get("/api/blogs");
      setBlogs(data.blogs);
    })();
  }, []);

  return (
    <>
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      {blogs.length && blogs.map((blog) => <p>{blog.title}</p>)}
    </>
  );
}

export default App;

Demo

Github Repo

You can find the full code in this repo

References

2
Subscribe to my newsletter

Read articles from Dharshan k directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dharshan k
Dharshan k

Passionate and results-driven Full-Stack Developer with more than 4 years of experience in managing the entire application lifecycle, from design to deployment. Proficient in React.js, MERN stack, and microservice architecture, with a track record of building scalable and high-performance applications. A self-motivated technology enthusiast with an entrepreneurial mindset, dedicated to building amazing products that drive business success.