nandorojo / expo-next-react-navigation

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

Sync dynamic routes with existing react-navigation URL structure #39

Closed davitykale-zz closed 3 years ago

davitykale-zz commented 3 years ago

I'm trying take advantage of Next.js's dynamic routes to be able to able to use Next.js's page routing with the exact same configuration I use for linking on iOS/Android.

Basically trying to do something like this:

// [page].js
const Page = () => {
  const {
    query: { page },
  } = useRouter();
  const { navigate } = useRouting();

  useEffect(() => {
    switch (page) {
      case "my_route":
        navigate({ routeName: "my_route" });
        break;
    }
  }, [navigate, page]);

  return <App />;
};

export default Page;

Is there a better way to do this? Or is what I am doing even feasible? As much as possible, would love to be able to navigate directly to a URL but have that tie into react-navigation.

nandorojo commented 3 years ago

I don’t really get it, you want to redirect to another page when the page loads?

To access the query, use getParam from useRouting. You’ll find it documented on the readme.

The routing pattern you’re describing doesn’t look right. You should just make a file in pages called my_route. Then name the screen in your stack my_route too.

nandorojo commented 3 years ago

Since you mentioned a dynamic route, you can get the dynamic param with getParam.

nandorojo commented 3 years ago

I might be able to help more if I can understand better what you’d like to achieve. Can you share your real app use case?

davitykale-zz commented 3 years ago

So, in my Expo application using react-navigation, I set the linking prop of my NavigationContainer as follows:

const linking = {
  config: {
      CreationPage: "create",
      ...,
  },
};

On web, if I serve my application using Next.js and navigate to www.[mydomain].com and then navigate to this page, the URL will change and I'll get www.[mydomain.com].com/create. If I refresh, however, it will serve a 404, because Next.js expects that I have pages/create.js.

Even if I were to make a pages/create.js file, I don't want to just export the CreatePage because there's other application code surrounding the app (e.g. a drawer / tab, depending on the screen size). I'm trying to figure out a way for me to use dynamic routing to make a generic [page].js file that I can basically say "Import my entire application and then navigate to the right page using the parameter provided".

I understand that's not exactly how Next.js is supposed to be use -- but I'm mostly trying to find the quickest route for me be able to navigate to /create and other URLs directly and get to the right page without needing to individually export every single page component.

mithunkalan commented 3 years ago

@davitykale did you solve this? I just started my project a few days ago and now im at your point. Static paths work fine. So I dont get the 404. But if i want to go to path "http...../items/item1" it doesn't work.

Dynamic paths do not work for me.

I have my config for linking

const linking = {
    prefixes: [prefix],
    config: {
      screens: {
        ProfileScreen: "profile",
        ItemScreen: "items/:name",
        NotFound: "*",
        P3: "p3",
      },
    },
  };

In the button

navigate({
   routeName: "items",
   params: { name: "item1" },
   web: { as: `/items/item1` },
});

With the stack defined for it as <Stack.Screen name="items" component={ItemScreen} />

What did you do to solve it?

mithunkalan commented 3 years ago

Nevermind. I think I solved it. Dont use sub-directories in the pages folder. Bit of an anti-pattern if you ask me.

nandorojo commented 3 years ago

The first one should work as long as you have a pages/items/[name].js file. Subdirectories are fine.

nandorojo commented 3 years ago

Also, use web.path instead of web.as.

mithunkalan commented 3 years ago

The first one should work as long as you have a pages/items/[name].js file. Subdirectories are fine.

Awesome this works. I didn't have the square brackets. Didn't realise it was explicit.

Any idea on the root path? If i go to localhost:3000/, the path changes to localhost:3000/profile. I would like to keep it as "/" Then if i go to any page, the header bar disappears.

nandorojo commented 3 years ago

I recommend reading the next router docs in general, the bracket stuff is all explicit, it can be confusing.

I don’t get the second question.

mithunkalan commented 3 years ago

If I start the server with "yarn next dev" Open browser to http://localhost:3000 The page loads fine. It has a header bar with just the page title like "My home". <Stack.Screen name="profile" component={ProfileScreen} options={{ title: 'My home' }}/> The browser address changes to http://localhost:3000/profile

I can find docs to allow me to keep the page as name="/" That is the root path question.

The header bar question is this: if i go to http://localhost:3000/items/item1. The header bar disappears. I think its because the browser does not remember the stack. The back button does not work, refresh forgets the params, etc. This 2nd question is messy. The reactnavigation documentation is a bit too vague for me. Will read nextrouter. Thanks Fernando

nandorojo commented 3 years ago

Yeah, stacks should only be used on native. On web, you’ll need your own header in pages/_app.js. See the example app to get an idea of page structure.

you should name your Home screen /

mithunkalan commented 3 years ago

@nandorojo Sorted. The directory structure is pretty rigid. So minor work to get mine to work with the standard setup. Then the big issue of funny 404s upon refresh was fixed by adding rewrites and redirects on the AWS amplify hosting console.