Skip to content

Compatibility with @react-navigation #6

@JohanObrink

Description

@JohanObrink

The plugin doesn't work with @react-navigation. I have found a few places where it breaks and possible ways to fix them but wanted to get your input first on how to proceed.

So far I have only edited code directly in the installed package.

Repro code

App.tsx

import { NavigationContainer } from '@react-navigation/native'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import { View } from 'react-native'

const Home = () => (<View />)
const Profile = () => (<View />)
const Navigator = createBottomTabNavigator()

export const App = () => (
  <NavigationContainer>
    <Navigator.Navigator >
        <Navigator.Screen name="Home" component={Home} />
        <Navigator.Screen name="Profile" component={Profile} />
      </Navigator.Navigator>
  </NavigationContainer>
)

App.spec.tsx

import { test, expect } from 'vitest'
import { render } from '@testing-library/react-native'
import { App } from './App'

test('it works', () => {
  const app = render(<App />)
  expect(app).toBeTruthy()
})

Requiring binaries

Running the test fails due to:

SyntaxError: Invalid or unexpected token
 ❯ Object.newLoader [as .js] ../../node_modules/pirates/lib/index.js:121:43
 ❯ Object.<anonymous> ../../node_modules/@react-navigation/elements/src/index.tsx:20:3

This because @react-navigation loads some binary assets:

export const Assets = [
  // eslint-disable-next-line import/no-commonjs
  require('./assets/back-icon.png'),
  // eslint-disable-next-line import/no-commonjs
  require('./assets/back-icon-mask.png'),
];

Quick and dirty solution:

if (!filename.endsWith('.png')) oldLoader(mod, filename);

Maybe all required binaries should just be ignored? Or replaced with Blobs? Also I am unfamiliar with pirates

  • how can this be done?

document and history are missing from global

After adding the quickfix for the pngs, the next error is:

ReferenceError: document is not defined
 ❯ ../../node_modules/@react-navigation/native/src/useDocumentTitle.tsx:32:7

...and after fixing that:

TypeError: Cannot read properties of undefined (reading 'state')
 ❯ Object.index ../../node_modules/@react-navigation/native/src/createMemoryHistory.tsx:35:33

Solution: add them

Object.defineProperties(globalThis, {
  // ...
  document: {
    configurable: true,
    enumerable: true,
    value: {},
    writable: true,
  },
  history: {
    configurable: true,
    enumerable: true,
    value: {},
    writable: true,
  },
})

window is not an event emitter

The next error is:

TypeError: window.addEventListener is not a function
 ❯ Object.listen ../../node_modules/@react-navigation/native/src/createMemoryHistory.tsx:217:14

...and this is where I ran out of quick and dirties. It seems the entire window object,
(represented as globalThis) should be augmented to work like it does in React Native.

I am happy to work on this but I think it needs your involvment to go in the direction you intended.

@sheremet-va What are your thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions