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 · 9 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 😬

@rodperottoni
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 😬

hey mate, I'm facing the same issues here. I have created a discussion up at the MSW repo: mswjs/msw#2359

@kettanaito
Copy link
Member

kettanaito commented Nov 19, 2024

I would love to help here but I have literally zero clue as to how Expo works. Someone with experience has to step in and champion this support.

We don't generally feature integrations for particular tools because MSW aims at environment support. In case of React native, that is most likely a Node.js environment (with oddities). What I mean by that, the fact that you need a proper place to defer your app's rendering isn't MSW's concern, it's Expo's concern (as well as giving you a clear entrypoint to configure). I find any recommendations like this hurting more than helping in the long run.

The best way forward is a functioning example. I tried setting one up with Expo in https://github.com/mswjs/examples, but the basic hello world Expo app fails to build in a PNPM monorepo.

What's next?

  1. Open a pull request to https://github.com/mswjs/examples, adding with-expo example. See existing examples for the feature set they must have (run locally, have at least one test, have .github/workflows automation configured).
  2. Ping me in the review. I will get to it as fast as I can to unblock people. I won't be able to review Expo setup itself, so there's where more eyes's the better.
  3. Hopefully, we merge it for everyone to reference.
  4. Then I include a link to the with-expo repo in the React native integration in the docs, making the example discoverable for everyone.

@kettanaito
Copy link
Member

Getting the example is one thing, but we also need someone to maintain it. If there's a volunteer, I will do all in my power for you to feel at home at MSW ❤️ There's no reason for Expo folks not to have the library working there.

@dpkbaba
Copy link

dpkbaba commented Dec 6, 2024

Getting the example is one thing, but we also need someone to maintain it. If there's a volunteer, I will do all in my power for you to feel at home at MSW ❤️ There's no reason for Expo folks not to have the library working there.

@kettanaito I'd be happy to support this. How do we get started?

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

9 participants