React-router: Pass complete match path to Route components

Created on 17 Aug 2016  路  3Comments  路  Source: ReactTraining/react-router

Redux is a great tool, but there are many React apps that don't need all that power. Unfortunately, when using React Router, passing the state of a stateful component to the props of stateless component without Redux is still a pain in the ass. It typically requires a series of switch...case or if...else if statements in a stateful component that duplicate the work of the routing system.

What I'd love to see is a this.props.route.match property (or whatever you want to call it) that contains the complete match path of a <Route /> component. That way, a stateful component can map the complete match path to a props object that'll eventually be sent to a cloned stateless component. For an example, see the following code example.

In summary, please throw non-Redux apps a bone by passing the complete match path to a Route component.

// index.js
import React from 'react'
import { render } from 'react-dom'
import { Router, Route, browserHistory } from 'react-router'
import App from './App'
import Foo from './Foo'
import Bar from './Bar'

render(
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <Route path="foo" component={Foo}>
      <Route path="bar/:baz" component={Bar}>
    </Route>
  </Router>,
  document.getElementById('app')
);
// App.js
import React from 'react';

const App = React.createClass({
  getInitialState() {
    return { foo: true, bar: false };
  },

  toggleFoo() {
    this.setState({ foo: !this.state.foo });
  },

  toggleBar() {
    this.setState({ bar: !this.state.bar });
  },

  getChildrenProps() {
    const props = {
      '/foo': {
        foo: this.state.foo,
        toggleFoo: this.toggleFoo
      },

      '/bar/:baz': {
        bar: this.state.bar,
        toggleBar: this.toggleBar,
        baz: this.props.location.params.baz
      }
    };

    // Look ma', no conditions
    return props[this.props.route.match];
  },

  render() {
    const children = React.cloneElement(
      this.props.children, 
      getChildrenProps()
    );

    return <div>{children}</div>;
  }
})

export default App;
// Foo.js
import React from 'react';

const Foo = React.createClass({
  handleClick() {
    this.props.toggleFoo();
  },

  render() {
    return <button onClick={this.handleClick}>{this.props.foo}</div>;
  }
})

export default Foo;
// Bar.js
import React from 'react';

const Bar = React.createClass({
  handleClick() {
    this.props.toggleBar();
  },

  render() {
    return <button onClick={this.handleClick}>
      {this.props.bar} - {this.props.baz}
    </div>;
  }
})

export default Bar;

Most helpful comment

I took the time to write out a code example in detail. I'd appreciate it if you did the same.

All 3 comments

Everything you need is on props.routes.

I took the time to write out a code example in detail. I'd appreciate it if you did the same.

We don't build a complete "matched path" in routing. The set of all matched routes is on props.routes.

Was this page helpful?
0 / 5 - 0 ratings