6

I'm still coming to grips with React and react-router, but I'm wondering how to use react-router to simply update application state without re-rendering DOM nodes.

For example, suppose I have:

<Router history={browserHistory}>
  <Route path="/" component={App}>
    <IndexRoute screen="main" />
    <Route path="settings" screen="sync" />
    <Route path="overview" screen="overview" />
  </Route>
</Router>

I'd like to re-use react-router's matching but simply update the App component's current screen.

The reason is that suppose in the above example I have three screens arranged horizontally with only one visible at a time. When the route changes I want to animate in the appropriate screen. If I do that by assigning a component to each route, react-router doesn't render the other screens until the route matches, and there's a noticeable lag for the screen to slide in.

However, if I keep all three screens in the DOM and simply toggle state to trigger CSS transitions there is no lag (since, with appropriate use of will-change, the browser can pre-render the off-screen layer).

I've tried half a dozen ways of achieving this but they're all very hacky or involve duplicating the matching code somewhat. What am I doing wrong?

Also, I'd like to avoid adding something like Redux just to fix this if possible.

brianskold
  • 809
  • 5
  • 10

1 Answers1

5

So you want something similar to Spectacle?

In your case I would place all the screens as children of the App component, and use react-router's params to know which screen you're on.

<Route path="/(:screen)" component={App}>

It will be avaialble as a prop to the App component:

class App extends React.Component {
  componentWillMount () {
    this.props.params.screen
  }
}

More about route params at react-router/injected-props

If you're having trouble with re-rendering you can use the component lifecycle method shouldComponentUpdate. Returning false in this method will prevent the component from re-rendering and you'll have the new props (which also include the route params).

class App extends React.Component {
  shouldComponentUpdate (nextProps) {
    nextProps.params.screen
    return false
  }
}
  • 1
    Thank you! I never thought of parameterizing the screen at the top-level. I'll look into shouldComponentUpdate too. Thank you so much! – brianskold Mar 29 '16 at 13:00
  • Thanks from me too :) ... with this difference that I'm using "componentDidUpdate" ... but the goal is achieved thanks to you ;) – pesho hristov Nov 08 '16 at 15:16