MSW(Mock Service Worker) in Next js first render not working
Asked Answered
A

2

6

I use msw with Next js. But at First render, cannot connect api this is index.tsx

import { useQuery } from "@tanstack/react-query";
import axios from "axios";

const Home = () => {
  const getFruit = async () => {
    const { data } = await axios.get("/api");

    return data;
  };

  const { data } = useQuery(["dfa"], getFruit);
  console.log("data: ", data);

  return <div>Hello world</div>;
};

export default Home;

And i capture log in dev tool enter image description here

In terminal compiling /_error (client and server).. error is showing. I write code in mocks/index.ts like

async function initMocks() {
  if (typeof window === "undefined") {
    const { server } = await import("./server");
    server.listen();
  } else {
    const { worker } = await import("./browser");
    worker.start();
  }
}

initMocks();

export {};

Also I check this code is running before index.tsx. I think msw work late then first rendering. Is it right? How can I solve this problem?

Archespore answered 28/9, 2022 at 10:28 Comment(1)
You can follow this official discussionUnlatch
S
2

Starting the worker is an asynchronous action, which may create a race condition with your application making requests on mount. If that's the case, please refer to the Deferred mounting recipe to enforce your application mount when the worker is ready.

from: https://mswjs.io/docs/getting-started/integrate/browser

My Solution (Next.js 13):

'use client';

import type { ComponentProps } from 'react';
import { createContext, useState, useEffect } from 'react';

const MSWContext = createContext('');

type Props = Omit<ComponentProps<typeof MSWContext.Provider>, 'value'>;

export default function MSWConfig({ children }: Props) {
  const [loaded, setLoaded] = useState(false);

  useEffect(() => {
    if (process.env.NODE_ENV === 'development') {
      // replace '@/mocks/browser' to yours
      import('@/mocks/browser')
        .then(({ worker }) => worker.start())
        .then(() => setLoaded(true));
    } else {
      setLoaded(true);
    }
  }, []);

  return (
    <MSWContext.Provider value={''}>
      {loaded ? children : <></>}
    </MSWContext.Provider>
  );
}
Scarlettscarp answered 26/8, 2023 at 17:31 Comment(0)
S
-1

I was faced with this same problem and decided to go this route. I have to say it all looked hacky to me but it managed to fix the problem for me.

useEffect(() => {
    if (process.env.NEXT_PUBLIC_API_MOCKING === "enabled") {
      import("../../mocks").then(({ initMocks }) => {
        initMocks().then(() => {
           // write your startup code here
          // boardsStore.fetchBoards();
        });
      });
    } else {
      // boardsStore.fetchBoards();
    }
  }, []);

I can see how this can be a problem with SSR and all but in my case it was sufficient, needless to say you can adapt this as a quick relief since this is not supposed to be production code anyway.

Simplicidentate answered 20/6, 2023 at 23:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.