Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJs - is it possible to set the url or querystring based on state of component tree

I have a component that has several nested components, specifically tabs, pills, etc. No all are visible at any one time.

I want to be able to set their default state/props based on the URL parameters (or URL) but I'm not clear how to achieve this in React.

For example, I have a component with two tabs (bootstrap). When the user selects the second tab, can i modify the URL with a parameter so that is the page is refreshed, the state of the currently selected tab is retained.

I've included the Router but cannot find any simple examples of what I'm trying to achieve.

What I'd like to be able to do is access/parse the query string parameters and set the state and ultimately properties of the child components.

Any advice is really welcome.

I can provide example of the tab component, but don't think it would add any value to the question.

like image 294
sambomartin Avatar asked Nov 10 '22 07:11

sambomartin


1 Answers

The way I've gone about this it to take advantage of React contexts. It's an undocumented but powerful feature that kind of acts like mutable props that can be accessed by a component and all its children.

I suggest Googling about it. It's a bit tough to wrap your mind around, but starts to make sense once you play with it. Here is an example excerpt from some code I am working on right now:

var React = require('react');

var Router = require('react-router'),
    Route = Router.Route,
    RouteHandler = Router.RouteHandler;

var ReactBootstrap = require('react-bootstrap'),
    DropdownButton = ReactBootstrap.DropdownButton,
    Nav = ReactBootstrap.Nav,
    Navbar = ReactBootstrap.Navbar;

var ReactRouterBootstrap = require('react-router-bootstrap'),
    MenuItemLink = ReactRouterBootstrap.MenuItemLink;

var Nav = React.createClass({
  render: function() {
    return (
      <Navbar brand='My Cool Page!' inverse toggleNavKey={0}>
        <Nav right eventKey={0}> {}
          <DropdownButton eventKey={2} title='Projects'>
            <MenuItemLink eventKey="1" to="myCoolPage" params={{ awesomeName: "matt" }}>Go to My Cool Page!</MenuItemLink>
          </DropdownButton>
        </Nav>
      </Navbar>
    );
  }
);

var MyCoolPage = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  getInitialState: function() {
    return {
      awesomeName: ''
    };
  },
  componentWillMount: function() {
    // Called once before the first render
    this.getAwesomeName();
  },
  componentWillReceiveProps: function(nextProps) {
    // Called when props change after the first render
    // From my testing, this is also called when a context changes
    this.getAwesomeName();
  },
  getAwesomeName: function() {
    var { router } = this.context;
    var awesomeName = router.getCurrentParams().awesomeName;

    this.setState({awesomeName: awesomeName});
  },
  render: function() {
    return (
      <h1>My awesome name is: {this.state.awesomeName}</h1>
    );
  }
});

var App = React.createClass({
  render: function() {
    return (
      <div>
        <Nav />
        <RouteHandler {...props} />
      </div>
    );
  }
});

var routes = (
  <Route handler={App}>
    <Route name="myCoolPage" path="myCoolPage/:awesomeName" handler={MyCoolPage} />
  </Route>
);

Router.run(routes, Router.HashLocation, function (Root) {
  React.render(<Root/>, document.body);
});
like image 166
Matthew Herbst Avatar answered Nov 14 '22 23:11

Matthew Herbst