React-router:传播路由组件的真正方法 props/state

React-router: true way to propagate route-component props/state

问题:通过location.state传递组件props/state不是反模式吗?你能推荐一个更好的方法吗?

我有一些社交网站,每个用户都可以在其中创建自己的个人资料。每个配置文件都是一个 UserProfile 组件,其路由方式如下:

ReactDOM.render((
    <Router history={History}>
        <Route path="/" component={App}>
            <IndexRoute component={Welcome} />
            <Route path="profile" component={UserProfile} />
        </Route>
    </Router>
), document.getElementById('app'));

而且我需要在用户点击时从我网站的多个位置重定向到特定的用户个人资料。我喜欢这样做:

// Where server response contains username, surname, some counters etc.
Service.getUserSummary(userId).then(response => {
  History.pushState(reponse, '/profile');
});

并在 UserProfile:

检索 response
module.exports = React.createClass({

  render() {
    // QUESTION: isn't it an anti-pattern? Is there any better way?
    const state = this.props.location.state,
          username = state.username,
          ............
  }
})

如果您处理以 ID 区分的配置文件,最好的方法是将 ID 包含在 URL:

ReactDOM.render((
    <Router history={History}>
        <Route path="/" component={App}>
            <IndexRoute component={Welcome} />
            <Route path="profile/:userId" component={UserProfile} />
        </Route>
    </Router>
), document.getElementById('app'));

id 将在 UserProfile 中作为 this.props.params.userId 使用。

更好的做法是在重定向之后从服务器加载数据,而不是之前或期间[=] 33=] 它。因此,您有 3 个阶段显示个人资料页面:

  1. 就在用户点击之前 link;
  2. 用户单击 link,路由器已重定向到用户配置文件页面,但它仍然是空的 ("loading...");
  3. 数据已从服务器到达,UserProfile 组件的状态已更新,并使用新数据重新呈现。

最简单的方法是在componentDidMount()方法中检索数据并设置为状态(参见https://facebook.github.io/react/tips/initial-ajax.html):

var UserProfile = React.createClass({
  getInitialState: function() {
    return {
      data: null,
    };
  },

  componentDidMount: function() {

    // Your code for fetching user data from server:
    Service.getUserSummary(this.props.params.userId).then(response => {
      if (this.isMounted()) {
        this.setState({
          data: response.data
        });
      }
    });
  },

  render: function() {
    if (!this.state.data) {

        // Rendering stage (2)
        return (<div>Loading...</div>);
    }

    // Rendering stage (3)
    return (
      <div>
        I am {this.state.data.userName}!
      </div>
    );
  }
});