1

The logic seems simple, though I've tried a half-dozen permutations to see if anything changes. I have no idea why react-router is behaving this way:

import React from 'react'
import { View, Text } from 'react-native'
import { observer, inject } from 'mobx-react'
import { NativeRouter, Link, Route, Redirect, Switch } from 'react-router-native'

import Welcome from './welcome'
import Tutorial from './tutorial'
import Plants from './plants'

@inject('store')
@observer
class Main extends React.Component {
  render() {
    const newUser = true //this.props.store.plants.length === 0
    const home = newUser ? '/welcome' : '/plants'
    return (
      <Switch>
        <Route path='/plants' component={Plants} />
        <Route path='/tutorial' component={Tutorial} />
        <Route path='/welcome' component={Welcome} />
        <Redirect to={home} />
        <Route path='/' component={Welcome} />
      </Switch>
    )
  }
}

export default Main

The final 'welcome' should be unnecessary, but I've put it there to test: if I remove the then welcome does appear, so it's clearly the that's causing a blank page to render.

This is the render() method of the top-level component:

return (
  <Provider store={store}>
    <NativeRouter>
      <Main />
    </NativeRouter>
  </Provider>
)

This is based on the example at https://reacttraining.com/react-router/native/guides/philosophy which shows a Switch, Route, and Redirect all being used without an enclosing Router:

const App = () => (
  <AppLayout>
    <Route path="/invoices" component={Invoices}/>
  </AppLayout>
)

const Invoices = () => (
  <Layout>

    {/* always show the nav */}
    <InvoicesNav/>

    <Media query={PRETTY_SMALL}>
      {screenIsSmall => screenIsSmall
        // small screen has no redirect
        ? <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
          </Switch>
        // large screen does!
        : <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
            <Redirect from="/invoices" to="/invoices/dashboard"/>
          </Switch>
      }
    </Media>
  </Layout>
)
hunterloftis
  • 13,386
  • 5
  • 48
  • 50
  • I might be misunderstanding your question, but if `newUser` is `true`, `home` will be `/welcome`, the redirect will happen, and it will render the third `Route` with path `/welcome`, i.e. the `Welcome` component. Is that not the desired behavior? – Tholle Jul 09 '18 at 01:07
  • 1
    That is the desired behavior, but that doesn't happen. Instead, it just shows a blank page. If I remove the redirect (leaving the default "/" to welcome), then welcome renders as expected, so I know the Welcome component is working. – hunterloftis Jul 09 '18 at 01:07
  • 1
    That's frustrating. The [web equivalent is working fine](https://codesandbox.io/s/qk4m6m5rkj). You are importing `NativeRouter`, but not using it. Have you forgotten about it, or are you using that outside of `Main`? – Tholle Jul 09 '18 at 01:09
  • 1
    It's being used at the top level (and passing its context down). – hunterloftis Jul 09 '18 at 01:14
  • 1
    Thanks for the link and the comment @Tholle, I wrapped the `Main` component inside a `NativeRouter` and now it's working as expected. I have no idea why that's necessary though as [the docs](https://reacttraining.com/react-router/native/guides/philosophy) suggest this shouldn't be necessary. – hunterloftis Jul 09 '18 at 01:18
  • 1
    If you'd like to answer with ^^ I'll accept; otherwise I can answer it with the working code. – hunterloftis Jul 09 '18 at 01:18

1 Answers1

2

Use the NativeRouter as the topmost component in your Main component and it will work as expected.

@inject('store')
@observer
class Main extends React.Component {
  render() {
    const newUser = true //this.props.store.plants.length === 0
    const home = newUser ? '/welcome' : '/plants'
    return (
      <NativeRouter>
        <Switch>
          <Route path='/plants' component={Plants} />
          <Route path='/tutorial' component={Tutorial} />
          <Route path='/welcome' component={Welcome} />
          <Redirect to={home} />
        </Switch>
      </NativeRouter>
    )
  }
}
Tholle
  • 108,070
  • 19
  • 198
  • 189
  • Thanks! This is surprising behavior given that their docs explicitly demo this without it being wrapped in a Router. The same code in the web version gives a nice error message instead of a blank page, which is very helpful: https://codesandbox.io/s/ppwq4o6qmj – hunterloftis Jul 09 '18 at 01:24
  • @hunterloftis You're welcome! Very interesting. I have very little insight into that space. It might be that a newer version of react-native is incompatible with that, or the documentation is outdated? I have no idea. – Tholle Jul 09 '18 at 01:26
  • 1
    Yeah, even weirder, the Switch and Routes all work without an extra wrapping; only Redirect fails. Makes me think it may be a bug in the native version. – hunterloftis Jul 09 '18 at 01:29