简体   繁体   中英

How to pass props to react-router 1.0 components?

Please note, that although the question itself is largely a duplicate of this , it concerns a different version which should support this. The linked question already accepted an answer on an old version

I'm pretty confused about what the intended workflow is.

Let's say I have a menu system where clicking on each item uses react-router to navigate to an area which pulls some data from the server.

url: yoursite/#/lists/countries
----------------------------
Billing Codes | <<Countries>> | Inventory Types 
---------------------------------------------------------
Countries:
---------------
Afghanistan
Azerbaijan
Belarus

with routes something like

Route #/lists component: Lists
   Route billing-codes component: BillingCodes
   Route countries component: Countries
   Route inventory-types component: InventoryTypes

I don't want to preload data from the server until an area is navigated to, so in my Countries component's on componentWillMount I fire an event (I'm using reflux but...whatever) that triggers a store to do an ajax request and update itself with the current list of countries.

Now the Countries component reacts to that change in state by updating the countries in its props. Except - reasonably - that generates an invariant error because I shouldn't be updating props on a child component, I should update it at the top level. But the top level is the router itself so now I'm just lost - where am I supposed to listen to changes and update props from?

( Cross-posted to the issue tracker as I think it needs some clearer documentation)

Reading the react-router 0.13 -> 1.0 Upgrade Guide and this example led me to the following:

{ this.props.children && 
     React.cloneElement(this.props.children, {newprop: this.state.someobject }) }

Instead of including the child components directly, we clone them and inject the new properties. (The guard handles the case where there is no child component to be rendered.) Now, when the child component renders, it can access the needed property at this.props.newprop .

The easy way is to just use this.state , but if you absolutely have to use this.props then you should probably extend Router.createElement .

First add the createElement prop to your Router render.

React.render(
  <Router history={history} children={Routes} createElement={createElement} />,
  document.getElementById('app')
);

Wrap all of your components in a new Container component.

function createElement(Component, props) {
    return <Container component={Component} routerProps={props} />;
}

Your Container component will probably look something like this. Pass an onLoadData function down to your component.

import React from 'react';
import _ from 'lodash';

class Container extends React.Component {
  constructor(props) {
    super(props);
    this.state = { props: props.routerProps };
  }

  onLoadData(props) {
    var mergedProps = _.merge(this.state.props, props);
    this.setState({ props: mergedProps });
  }

  render() {
    var Component = this.props.component;
    return <Component {...this.state.props} onLoadData={this.onLoadData.bind(this)} />;
  }
}

Then from your loaded component, when you get your data back from the server, just fire this.props.onLoadData(data) and the data will be merged with your current props.

Read the Router.createElement Documentation

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM