nandorojo / expo-next-react-navigation

⛴ Make Next.js and react-navigation play nicely together with an Expo/React Native Web app.
408 stars 32 forks source link

TypeError: undefined is not an object (evaluating 'scene.descriptor.route.key') #77

Closed kenchoong closed 3 years ago

kenchoong commented 3 years ago

Try to create a simple Navigation between 2 screens, followed the example provider.

/screens/Login.tsx

export const Login: React.FC<LoginProps> = ({ }) => {
    const { navigate } = useRouting()

    const onPress = () => {
        /* */
    }

    return (
        <Layout>
            <LoginForm onPress={onPress} />
        </Layout>
    );
}

``/screens/SignUp.tsx

export const SignUp: React.FC<SignUpProps> = () => {
    return (
        <Layout>
            <SignUpForm />
        </Layout>
    );
}

/pages/login.tsx export { Login as default } from '../screens/Login'

/pages/sign-up.tsx tsx export { SignUp as default } from '../screens/SignUp'

App.tsx (Entry point of the app)

import React from 'react';
import 'react-native-gesture-handler';

import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack'

import { Login } from './screens/Login';
import { SignUp } from './screens/SignUp';

export default function App() {

  const Stack = createStackNavigator()

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Login">
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="SignUp" component={SignUp} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Then I run expo start, the error look like this:

Here is the complete error logs 

TypeError: undefined is not an object (evaluating 'route.key')

This error is located at:
    in CardContainer (at CardStack.tsx:649)
    in RNSScreen (at createAnimatedComponent.js:165)
    in AnimatedComponent (at createAnimatedComponent.js:215)
    in ForwardRef(AnimatedComponentWrapper) (at src/index.native.tsx:147)
    in Screen (at Screens.tsx:37)
    in MaybeScreen (at CardStack.tsx:642)
    in RNSScreenContainer (at src/index.native.tsx:186)
    in ScreenContainer (at Screens.tsx:20)
    in MaybeScreenContainer (at CardStack.tsx:561)
    in RCTView (at View.js:34)
    in View (at Background.tsx:13)
    in Background (at CardStack.tsx:559)
    in CardStack (at StackView.tsx:437)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at SafeAreaProviderCompat.tsx:46)
    in SafeAreaProviderCompat (at StackView.tsx:430)
    in RCTView (at View.js:34)
    in View (at StackView.tsx:429)
    in StackView (at createStackNavigator.tsx:118)
    in Unknown (at createStackNavigator.tsx:117)
    in StackNavigator (at App.tsx:17)
    in EnsureSingleNavigator (at BaseNavigationContainer.tsx:411)
    in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:91)
    in ThemeProvider (at NavigationContainer.tsx:90)
    in ForwardRef(NavigationContainer) (at App.tsx:16)
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in DevAppContainer (at AppContainer.js:121)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)
    in AppContainer (at renderApplication.js:39)

TypeError: undefined is not an object (evaluating 'scene.descriptor.route.key')

This error is located at:
    in HeaderContainer (at StackView.tsx:316)
    in RCTView (at View.js:34)
    in View (at Background.tsx:13)
    in Background (at CardStack.tsx:559)
    in CardStack (at StackView.tsx:437)
    in RNCSafeAreaProvider (at SafeAreaContext.tsx:76)
    in SafeAreaProvider (at SafeAreaProviderCompat.tsx:46)
    in SafeAreaProviderCompat (at StackView.tsx:430)
    in RCTView (at View.js:34)
    in View (at StackView.tsx:429)
    in StackView (at createStackNavigator.tsx:118)
    in Unknown (at createStackNavigator.tsx:117)
    in StackNavigator (at App.tsx:17)
    in EnsureSingleNavigator (at BaseNavigationContainer.tsx:411)
    in ForwardRef(BaseNavigationContainer) (at NavigationContainer.tsx:91)
    in ThemeProvider (at NavigationContainer.tsx:90)
    in ForwardRef(NavigationContainer) (at App.tsx:16)
    in App (created by ExpoRoot)
    in ExpoRoot (at renderApplication.js:45)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:106)
    in DevAppContainer (at AppContainer.js:121)
    in RCTView (at View.js:34)
    in View (at AppContainer.js:132)

package.json

"dependencies": {
    "@react-navigation/native-stack": "^6.0.7",
    "@react-navigation/stack": "^6.0.7",
   "expo-next-react-navigation": "^1.1.14"
    "next": "^11.1.0",
}

The example provided looks outdated, so is it still possible to use this library with React-navigation v6.0?

What I doing wrong that makes me get the error above?

nandorojo commented 3 years ago

Yeah the example is old. FYI if you write tsx after your first three back ticks in a code sample, it formats it with colors, making it easier to read.

it seems like you might be trying to access navigation state inside of a component called HeaderContainer?

Have you isolated this error to the useRouting function?

kenchoong commented 3 years ago

Have you isolated this error to the useRouting function?

How can I isolated the error? (Sorry, quite new to expo)

I dont have any component named HeaderContainer and CardContainer.(I updated the complete error logs in the question)

For now, App.tsx is the entry point of the app. Once I open the app using Expo, the error comes out. I looks like, the code havent reach to useRouting in Login component, the error already occurred. I also not sure why.

According to my app structure, am I doing it right?

Do you have any suggestion?

kenchoong commented 3 years ago

Solved this by install @react-navigation/native library

kenchoong commented 3 years ago

Now having a new error:

Error: Couldn't find a navigation object. Is your component inside a screen in a navigator?

This happened when I access useRouting() inside my Login.tsx

./screens/Login file

export const Login: React.FC<LoginProps> = ({ }) => {
    const { navigate } = useRouting() //problem is happened here

    const onPress = () => {
        /* */
    }

    return (
        <Layout>
            <LoginForm onPress={onPress} />
        </Layout>
    );
}

I tried to use useNavigation like this

import { useNavigation } from '@react-navigation/native';

export const Login: React.FC<LoginProps> = ({ }) => {
    const { navigate } = useNavigation() // if useNavigation it have no problem. 
}

My pages/login.tsx only have 1 line, same as example (This is the page in Next js)

export { Login as default } from '../screens/Login'

This library is very great, just I dont know what happened to cause this error, even though I follow the structured like example provided.

Question: What else I need to do? What I missing out?

nandorojo commented 3 years ago

I think I just need some more info…that error happens if your app doesn’t have NavigationContainer wrapping it at the root. However, it wouldn’t make sense on web.

To confirm, you’re using the @expo/next-adapter setup right?

nandorojo commented 3 years ago

First things first, have you followed all instructions for expo/next-adapter, as well as react-navigation installation?

kenchoong commented 3 years ago

Yes, I setup @expo/next-adapter, checked

All the react-navigation is done.

I am using the latest react-navigation, which is version 6.0.

This is from example, which I think the problem is come from here?

const AppNavigator = createStackNavigator({
  '/': Home,
  Profile,
})

Cause I read react navigation docs, since version 5.x the createStackNavigator is using just like this:

const Stack =  createStackNavigator()

Not very sure is it caused by this

nandorojo commented 3 years ago

Yeah that example uses v4 😬 I should update when I have time

kenchoong commented 3 years ago

So I should update it in here right?

<NavigationContainer>
      <Stack.Navigator> // over here right? 
        <Stack.Screen name="Login" component={Login} />
        <Stack.Screen name="SignUp" component={SignUp} />
      </Stack.Navigator>
    </NavigationContainer>

If so, how can I do that? Any idea?

kenchoong commented 3 years ago

I have tried this by followed this docs:

const linking = {
    prefixes: ['https://localhost:3000', 'localhost:3000://'],
    config: {
      screens: {
        Login: {
          path: 'login'
        },
        SignUp: {
          path: 'sign-up'
        }
      },
    },
  };

<NavigationContainer linking={linking}>

</NavigationContainer>

But still unable to do that , still getting this error

Error: Couldn't find a navigation object. Is your component inside a screen in a navigator?

So the main reason of this error, is come from useRouting(). Cause when I use useNavigation, then the error gone.

Look at the source code here as well, which is using react-navigation-hooks ,.

import { useNavigation } from 'react-navigation-hooks'

Therefore this should be the problem, as mention here

I wonder, in use-routing file just using react navigate useNavigation directly, is it still working? 🤣

kenchoong commented 3 years ago

In order to try to support React-navigation v5.0, here is some of my attempt

  1. remove react-navigation-hooks library
  2. yarn add @react-navigation/native
  3. In /use-routing/index.ts , done this :
    
    import { useNavigation, useRoute } from '@react-navigation/native'

export default function useRouting() { const { navigate: nav, getParam: grabParam, // this need to remove push: pushTo, // this also need to remove goBack, } = useNavigation()



Cause by the breaking changes here 
- No more `getParam`: https://reactnavigation.org/docs/5.x/upgrading-from-4.x#no-more-getparam
- `Push is changed  : https://reactnavigation.org/docs/5.x/upgrading-from-4.x#push

So no more `getParam` and `push`, what should we do? Just remove that 2 function? Or any better way? 
kenchoong commented 3 years ago

So far what I tried is this:

import { useNavigation, useRoute, StackActions } from '@react-navigation/native'

export default function useRouting() {
  const {
    navigate: nav,
    goBack
  } = useNavigation()

  const route = useRoute()
  const navigation = useNavigation()

 // here subsitute the grabParam function 
  const grabParam = (param: string, fallback?: unknown) => {
    return route.params?.[param] ?? fallback;
  }

// here subsitute the push function 
 const push = useCallback(
    (route: NavigateTo) => {
      const stackActions = StackActions.push(route.routeName, route.params)
      navigation.dispatch(stackActions)
    },
    [navigation]
  )

Therefore the final use-routing/index.ts file will be:

import { useNavigation, useRoute, StackActions } from '@react-navigation/native'
import { useCallback } from 'react'
import { NavigateTo } from './types'

export default function useRouting() {
  const {
    navigate: nav,
    goBack
  } = useNavigation()

  const route = useRoute()
  const navigation = useNavigation()

  const grabParam = (param: string, fallback?: unknown) => {
    return route.params?.[param] ?? fallback;
  }

  const navigate = useCallback(
    <To extends NavigateTo = NavigateTo>(route: To) => {
      nav({
        routeName: route.routeName || '/',
        params: route.params,
      })
    },
    [nav]
  )

  const push = useCallback(
    (route: NavigateTo) => {
      const stackActions = StackActions.push(route.routeName, route.params)
      navigation.dispatch(stackActions)
    },
    [navigation]
  )

  const getParam = <Param>(param: string, fallback?: unknown): Param => {
    const value: Param = grabParam(param, fallback)
    return value
  }

  return { navigate, getParam, push, goBack: () => goBack() }
}

Not yet try it. Just state my attempt first

nandorojo commented 3 years ago

I’m pretty confused here. useRouting is exported by this library. Why are you making your own?

nandorojo commented 3 years ago

Oh, did you install the wrong version?

it should be

expo install expo-next-react-navigation@v5

kenchoong commented 3 years ago

Oh, did you install the wrong version?

it should be

expo install expo-next-react-navigation@v5

Lol, sorry, I forgot, it mentions in the docs Version 1.x supports v5. (Just now I tot this library not supported V5)

Before this, I use yarn add expo-next-react-navigation@v5 My package json having this: "expo-next-react-navigation": "^1.1.14".

Then I try with expo install expo-next-react-navigation@v5 package.json still the same

Also having the same problem

Error: Couldn't find a navigation object. Is your component inside a screen in a navigator?

And this error as well [Unhandled promise rejection: Error: Couldn't find a navigation object. Is your component inside a screen in a navigator?]

I even removed the package, then reinstall again, but still having the same problem above

nandorojo commented 3 years ago

Can you make a fresh project that’s really minimal and send the git repo? I’m finding this very hard to debug.

kenchoong commented 3 years ago

Can you make a fresh project that’s really minimal and send the git repo? I’m finding this very hard to debug.

Ok, may be few hours later. Thank you for your help

nandorojo commented 3 years ago

This might help in general as a template for expo and next

https://github.com/axeldelafosse/expo-next-monorepo-example

kenchoong commented 3 years ago

Sir, I created a new repo that exactly the same structure that I having now. Even in new repo, I still having the same error.

https://github.com/kenchoong/navigation-testing

Followed your docs ,react-navigation docs and also your example. I not sure what I missing out.

Kindly take a look at my repo please.

kenchoong commented 3 years ago

https://github.com/nandorojo/expo-next-react-navigation/issues/14#issuecomment-603278505

Try this as well, still not working

kenchoong commented 3 years ago

Can you make a fresh project that’s really minimal and send the git repo? I’m finding this very hard to debug.

Sir, just keep track, do you look at my fresh repo?

nandorojo commented 3 years ago

Thanks for the repro, I’ll look when I am available.

Before sending follow ups, please remember that this is open source, and you’re not paying me to help you.

kenchoong commented 3 years ago

Thanks for the repro, I’ll look when I am available.

Before sending follow ups, please remember that this is open source, and you’re not paying me to help you.

Ya I understand. Thank you for your help

nandorojo commented 3 years ago

@kenchoong thanks for your patience here. This is the solution for now:

Add this to your package.json:

{
  "resolutions": {
    "@react-navigation/native": "6.0.2"
  }
}

It ran fine for me after doing that. I'll release a new version of this lib with v6 support shortly.

nandorojo commented 3 years ago

I added the solution to the README: https://github.com/nandorojo/expo-next-react-navigation/blob/master/README.md#for-react-navigation-v6

nandorojo commented 3 years ago

Fixed in version 2.0.2 🥳

yarn add expo-next-react-navigation
nandorojo commented 3 years ago

Here's your example app image

kenchoong commented 3 years ago

Tq very much sir, later I check it out

kenchoong commented 3 years ago

Just tried it out sir, having this error

./node_modules/expo-next-react-navigation/build/components/Link/index.web.js:39:22
Syntax error: Unexpected token, expected ","

  37 |         pathname,
  38 |     }), [pathname, query]);
> 39 |     return (<NextLink passHref {...nextLinkProps} href={href} as={web?.as} prefetch={web?.prefetch} scroll={web?.scroll} replace={web?.replace} shallow={web?.shallow}>
     |                       ^
  40 |         {isText ? (<Text ref={ref} accessibilityRole="link" style={style}>
  41 |             {children}
  42 |           </Text>) : (<View accessibilityRole="link" style={style}> 

For Next js. For mobile, it working fine.

kenchoong commented 3 years ago

Updated the index.js here

https://github.com/kenchoong/navigation-testing/blob/main/pages/index.js

You can yarn start to test it with web.

For mobile I already test it out, it working fine. Just next js having problem

nandorojo commented 3 years ago

Thanks for the heads up, I’ll test it tomorrow.

nandorojo commented 3 years ago

Oh I think I know the issue…next 11 requires a monorepo with expo. This example by @axeldelafosse should fix it https://github.com/axeldelafosse/expo-next-monorepo-example

The reason is that expo and next need different Babel configs.

axeldelafosse commented 3 years ago

Or you can try with "@expo/next-adapter": "^3.1.0". The latest version includes a fix for the Babel config. But it's still a very good idea to use a monorepo when using Next.js and Expo.

kenchoong commented 3 years ago

Oh I think I know the issue…next 11 requires a monorepo with expo. This example by @axeldelafosse should fix it https://github.com/axeldelafosse/expo-next-monorepo-example

The reason is that expo and next need different Babel configs.

Thanks will try for monorepo later. thanks

kenchoong commented 3 years ago

Or you can try with "@expo/next-adapter": "^3.1.0". The latest version includes a fix for the Babel config. But it's still a very good idea to use a monorepo when using Next.js and Expo.

Sir I tried this, I already upgrade to "@expo/next-adapter": "^3.1.0", but end up getting this error:

./node_modules/expo-next-react-navigation/build/components/Link/index.web.js
Module not found: Can't resolve 'react/jsx-dev-runtime' in 'D:\Desktop\navigation-test\node_modules\expo-next-react-navigation\build\components\Link'

May be something else I miss out, not sure, just state the problem here

Attach a complete error logs as well:

error - ./node_modules/expo-next-react-navigation/build/components/Link/index.web.js
Module not found: Can't resolve 'react/jsx-dev-runtime' in 'D:\Desktop\navigation-test\node_modules\expo-next-react-navigation\build\components\Link'
Error: Cannot find module 'react/jsx-dev-runtime'
Require stack:
- D:\Desktop\navigation-test\.next\server\pages\index.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\require.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\load-components.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\api-utils.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\next-server.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\next.js
- D:\Desktop\navigation-test\node_modules\next\dist\server\lib\start-server.js
- D:\Desktop\navigation-test\node_modules\next\dist\cli\next-dev.js
- D:\Desktop\navigation-test\node_modules\next\dist\bin\next
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:966:15)
    at Function.mod._resolveFilename (D:\Desktop\navigation-test\node_modules\next\dist\build\webpack\require-hook.js:96:28)
    at Function.Module._load (internal/modules/cjs/loader.js:842:27)
    at Module.require (internal/modules/cjs/loader.js:1026:19)
    at require (internal/modules/cjs/helpers.js:72:18)
    at Object.react/jsx-dev-runtime (D:\Desktop\navigation-test\.next\server\pages\index.js:7067:18)
    at __webpack_require__ (D:\Desktop\navigation-test\.next\server\webpack-runtime.js:25:42)
    at Object../node_modules/expo-next-react-navigation/build/components/Link/index.web.js (D:\Desktop\navigation-test\.next\server\pages\index.js:44:79)
    at __webpack_require__ (D:\Desktop\navigation-test\.next\server\webpack-runtime.js:25:42)
    at Object../node_modules/expo-next-react-navigation/build/components/index.js (D:\Desktop\navigation-test\.next\server\pages\index.js:169:63) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'D:\\Desktop\\navigation-test\\.next\\server\\pages\\index.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\require.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\load-components.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\api-utils.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\next-server.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\next.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\server\\lib\\start-server.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\cli\\next-dev.js',
    'D:\\Desktop\\navigation-test\\node_modules\\next\\dist\\bin\\next'
  ]
}

A complete reproduce project here: https://github.com/kenchoong/navigation-testing

nandorojo commented 3 years ago

Can you reproduce in the monorepo instead? I think this is due to the custom Babel config which is solved in the monorepo. You can just fork it

kenchoong commented 3 years ago

Can you reproduce in the monorepo instead? I think this is due to the custom Babel config which is solved in the monorepo. You can just fork it

Thanks later I try in monorepo. tq

kenchoong commented 3 years ago

Monorepo works. Thanks