Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation missing on how to integrate with Expo App Router #372

Open
joao-arau-symphony opened this issue Feb 21, 2024 · 5 comments
Open

Comments

@joao-arau-symphony
Copy link

joao-arau-symphony commented Feb 21, 2024

As of today, The React Native integration documentation recommends delaying application initialization until the mocks are loaded like so:

enableMocking().then(() => {
  AppRegistry.registerComponent(appName, () => App)
})

However when using Expo App router the entry point of the application is internal to the library and not available to freely configure.

For apps using App Router, Expo recommends placing initialization code in the RootLayout file instead, but it would be helpful if there is an official recommendation from MSW on how avoid potential race conditions related to app initialization.

@sargentieri
Copy link

Do you have a working example of MSW with expo by chance?

@uroge
Copy link

uroge commented Jun 14, 2024

index.js file is where you set the entry for expo-router.
Instead of importing "expo-router/entry" you could set the entry point manually, and ensure that mocking is enabled:

import { registerRootComponent } from 'expo';
import { ExpoRoot } from 'expo-router';

export const App = () => {
  const ctx = require.context('./src/app');

  return <ExpoRoot context={ctx} />;
};

async function enableMocking() {
  if (!__DEV__) {
    return;
  }

  await import('./msw.polyfills');
  const { server } = await import('./src/server');

  server.listen();
}

enableMocking().then(() => {
  registerRootComponent(App);
});

@dpk-baba
Copy link

dpk-baba commented Sep 22, 2024

@uroge

index.js file is where you set the entry for expo-router. Instead of importing "expo-router/entry" you could set the entry point manually, and ensure that mocking is enabled:

import { registerRootComponent } from 'expo';
import { ExpoRoot } from 'expo-router';

export const App = () => {
  const ctx = require.context('./src/app');

  return <ExpoRoot context={ctx} />;
};

async function enableMocking() {
  if (!__DEV__) {
    return;
  }

  await import('./msw.polyfills');
  const { server } = await import('./src/server');

  server.listen();
}

enableMocking().then(() => {
  registerRootComponent(App);
});

This is not working for me. I get the following error:

ERROR Invariant Violation: "main" has not been registered. This can happen if:

  • Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
  • A module failed to load due to an error and AppRegistry.registerComponent wasn't called., js engine: hermes

This is my package.json file where I have set the entry point:

"name": "myreactapp",
  "main": "index.js",
  "version": "1.0.0",

And this is my index.js file:

import { registerRootComponent } from "expo";
import { ExpoRoot } from "expo-router";

export const App = () => {
  const ctx = require.context("./app");

  return <ExpoRoot context={ctx} />;
};

async function enableMocking() {
  if (!__DEV__) {
    return;
  }

  await import("./msw.polyfills");
  const { server } = await import("@/mocks/server");

  server.listen();
}

enableMocking().then(() => {
  registerRootComponent(App);
});

I am using file based routing and my app directory is in the root directory:
Screenshot_2024-09-22_19-12-05

What am I missing here?

@Maren-Osnabrug
Copy link

Maren-Osnabrug commented Oct 16, 2024

Not sure if this will fix everything for you but I found this answer very helpful to get my implementation up and running 😄
So I also have the change you have in the package.json and then in the index.js:

// import all polyfills 
import "fast-text-encoding";
import "react-native-url-polyfill/auto";
// that's probably what you have in `msw.polyfills.js`

// end with the entry from Expo Router
import "expo-router/entry";

I can then call server.listen() in my root layout file. Hope it helps!

@vonkanehoffen
Copy link

Trying to get this working myself and not having much luck. I tried all suggestions above & from the current docs.
I always get:

ReferenceError: Property 'Document' doesn't exist

when MSW tries to mock a request, so I dunno if it's missing some polyfill somewhere?

I made a minimal reproduction here:

https://github.com/vonkanehoffen/msw-minimal

Same story when I:

Any ideas @kettanaito or anyone? Presume I'm doing something wrong but no idea what 😬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants