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

Thoughts #40

Open
steida opened this issue Sep 8, 2016 · 14 comments
Open

Thoughts #40

steida opened this issue Sep 8, 2016 · 14 comments
Labels

Comments

@steida
Copy link

steida commented Sep 8, 2016

What do you think about https://github.com/exponentjs/ex-navigation? Isn't it the better approach?Also, I'm not sure whether it makes sense to rely on RR3 when RR4 should be universal and entirely different.

@jmurzy
Copy link
Owner

jmurzy commented Sep 8, 2016

Great questions 💯

I would say it really comes down to personal preference. Calling one better than the other would be unfair. This project was born out of my frustration while searching for a router, and I had different goals in mind when I wrote it; namely,

  • URL Driven Development
  • Learn once, write anywhere: knowledge and proven idioms from react-router can be reused while extending them as necessary to allow navigation semantics unique to native platforms
  • First class deep linking support
  • Cross-platform

Not sure if you can beat the brevity of this example app with any other router out there (not to mention the addressBar you get for free as in free 🍻 ), and if you're using React Router on the web, then not sure why you would want to learn a completely new library to do pretty much the same thing. Also, keep in mind that there is no magic here. Everything is highly customizable if you need access to NavigationExperimental itself to do fancy transition animations, &c.

As for React Router v4 support, I can't say much until I see the CHANGELOG, and I'm not sure what kind of out-of-the-box support it'll have for React Native.

But really, for me, it is all about the community. I'm just doing as much as I can to contribute back. If we as a community come up with a better solution, I'm all ears. Navigation on mobile is a challenging task, and having different flavors is, IMO, only healtier as the community weighs the pros and cons of each approach.

🍺

@jmurzy jmurzy added the question label Sep 8, 2016
@jonathanglasmeyer
Copy link
Collaborator

We are developing an app for react web and react native with a shared codebase, only leaf view components are reiimplemented, the rest of the code is universal as in cross-plattform. We use react router onEnter hook to fetch data etc. react-router-native allows us to use these parts of the code (all container components to be exact) in both environments.
The code quality / complexity / size metrics are totally awesome. :)👍🏻🎉

@steida
Copy link
Author

steida commented Sep 9, 2016

@jonathanewerner I maintain universal dev stack, where I experiment with sharing code across all platforms. https://github.com/este/este

@chirag04
Copy link

chirag04 commented Sep 9, 2016

It would be nice to hear from the authors of ex-navigation as well. cc @skevy @notbrent

(Disclaimer: I'm using ex-navigation in production but want the community to come up with best practices)

@jbrodriguez
Copy link

Routing/Navigation is currently the biggest pain point in RN from my standpoint.

Additionally, Android always seem to be an afterthought.

I'm currently using a fork of https://github.com/Qwikly/react-native-router-redux, since it provided me with the easiest API.

I've looked at ex-navigation and I liked the API, but I also think that react-router-native is quite powerful.

Here's hoping that by year's end we can have a sanctioned navigation component.

@brentvatne
Copy link

brentvatne commented Sep 14, 2016

This is really neat! Looking forward to seeing if this approach holds up in a large app. Maybe I don't understand the routing correctly, how would you implement something like this flow in react-router / react-router-native?

  • On Facebook news feed
  • Tap on a friend's name
  • Tap on their photos
  • Tap on the name of someone tagged in the photos
  • Tap about
  • Tap one of the pages that they like
  • Tap on someone's profile
  • etc....

/feed/friend-name/photos/friend/friend-name-two/about/page-name/friend-name-three?

What if you do the same flow but start from your profile?

/my-profile/friend-name/photos/friend/friend-name-two/about/page-name/friend-name-three?

What would the route definition look like?

@brentvatne
Copy link

@jbrodriguez

I've looked at ex-navigation and I liked the API, but I also think that react-router-native is quite powerful.

Could you elaborate on this? Always looking to improve ex-navigation, if there is something missing from it that you need, let us know. Check out this demo of shared element transitions for example (original tweet). Also ships with navigation drawer, tab, sliding tab, built-in support for alerts, is flow typed, handles back button automatically, powerful api for customization, etc.

@jmurzy
Copy link
Owner

jmurzy commented Sep 14, 2016

@brentvatne Thanks!

Here's what your routes config would look like for something akin to the Facebook app:

<Router>
  <TabsRoute path="master" component={Master}>
    <StackRoute path="/feed" component={Feed}>
       <Route path="profile/:userId" component={Profile} overlayComponent={ProfileNavBar} />
       <Route path="profile/:userId/photos" component={Photos} overlayComponent={PhotosNavBar} />
       <Route path="profile/about" component={About} overlayComponent={AboutNavBar} />
       <Route path="page/:pageId" component={Page} overlayComponent={PageNavBar} />
    </StackRoute>
  </TabsRoute>
</Router>

That's it 🤖

This will render a NavigationTransitioner (for "stack of cards") nested in another NavigationTransitioner (for tabs aka disable animations). You could recursively go as deep as you'd like. They don't have to be at the root level either. So you could put tabs inside others tabs as in this example.

Also, <Route>, <TabsRoute> and <StackRoute> all have stock reducers with sensible defaults associated with them that spit out navigationStates that can then be given to NavigationExperimental. React Router is only responsible for the recursive rendering of navigational components and user components are dynamically looked up and passed to NavigationExperimental at runtime. So <Route>'s you nest in <TabsRoute> and <StackRoute> will be handed down to their parent NavigationTransitioner's when a matching route is found.

You can then just tap on "links" to manipulate the navigationState:

Tap on a friend's name:

<Link to="/feed/profile/brent">

Tap on their photos:

<Link to="/feed/profile/brent/photos">

Tap on the name of someone tagged in the photos:

<Link to="/feed/profile/brent/about">

Tap about:

<Link to="/feed/profile/brent/about">

Tap one of the pages that they like

<Link to="/feed/profile/brentvatne/about">

Tap on someone's profile

<Link to="/feed/profile/jake">

At any given time, you can do router.pop(-n) or use <Pop> to transition back to a previous scene.

Also, the default reducers are completely customizable per route if you want to interpret a request completely independent of the browser behavior, and you can add custom animations by registering a new transition with the transitionRegistry:

transitionRegistry.addHandler(
  "sliding-tab",
  NavigationCardStackStyleInterpolator.forHorizontal,
  NavigationCardStackPanResponder.forHorizontal,
);

...

<TabsRoute transition="sliding-tab">

This gives you a sliding card animation wherever you want it.

I know I really should sit down and start writing documentation. 😞

🍺

@brentvatne
Copy link

@jmurzy - I'm not sure that answer is correct, because you would be popping routes to go back, no? In the FB app and most apps you can keep going infinitely deep in the stack

@brentvatne
Copy link

brentvatne commented Sep 14, 2016

Tap on a friend's name:

<Link to="/feed/profile/brent">

Tap on their photos:

<Link to="/feed/profile/brent/photos">

Tap on the name of someone tagged in the photos:

<Link to="/feed/profile/brent/photos/jake">

Tap about:

<Link to="/feed/profile/brent/photos/jake/about">

Tap one of the pages that they like

<Link to="/feed/profile/brentvatne/photos/jake/about/react-router">

Tap on someone's profile

<Link to="/feed/profile/brentvatne/photos/jake/about/react-router/profile/steida">

Is this wrong? Would you need to have all of this to maintain history and be able to press back 5 times to get back to the root?

@jbrodriguez
Copy link

@jbrodriguez

I've looked at ex-navigation and I liked the API, but I also think that react-router-native is quite powerful.
Could you elaborate on this?

@brentvatne sure, I'm using react-router in a web app and it's very simple conceptually. I think react-router-native is powerful because it offers the same mental model in a native app.

Having said that and knowing navigation in both platforms is different, I certainly like the approach by ex-navigation.

In the next couple of days, I'll free up some time to go deeper into both solutions and have a better comparison (at least from my perspective).

At the end of the day, I'm just looking for something that is simple to use :)

@jmurzy
Copy link
Owner

jmurzy commented Sep 14, 2016

@brentvatne Oh no. Those would be some ugly looking URIs 😅

I know this can be a bit confusing. It's cyclic once you enter <StackRoute>. Notice in this example, you can keep pressing on Random and it'll look up the matching route, and create a completely independent scene. It's not a 1-1 relationship. So you can keep going infinitely deep in the stack.

If you do

router.push(`/detail/red`)

and then do it again

router.push(`/detail/red`)`

your scenes.length for the parent transitioner would be 2. A new instance is dynamically looked up and added to your navigationState.

@brentvatne
Copy link

ooh I see. thanks for clarifying @jmurzy! what would the URL be at the end of that chain of events then?

@jmurzy
Copy link
Owner

jmurzy commented Sep 14, 2016

@brentvatne Final URL would be the last navigated path. Same as the browser behavior. In above case, it is /feed/profile/jake.

And if you wanted to have another tab as in the notifications tab in the Facebook app. You could just factor out your common tabs and pass it to both <TabsRoute>.

For example, if you tap on a new friend's request in the Notifications tab:

router.push(`/notifications/profile/jake`)

would push a new Profile scene to the Notifications transitioner.

Alternatively, you could do:

router.push(`/feed/profile/jake`)

to navigate to the Feeds tab and have it push to the Feeds transitioner instead.

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

No branches or pull requests

6 participants