reactjs-如何通过React Router传递状态?

这是引起我麻烦的文件:

var Routers = React.createClass({

  getInitialState: function(){
    return{
      userName: "",
      relatives: []
    }
  },

  userLoggedIn: function(userName, relatives){
    this.setState({
      userName: userName,
      relatives: relatives,
    })
  },

  render: function() {
    return (
      <Router history={browserHistory}>
        <Route path="/" userLoggedIn={this.userLoggedIn} component={LogIn}/>
        <Route path="feed" relatives={this.state.relatives} userName={this.state.userName} component={Feed}/>
      </Router>
    );
  }
});

我正在尝试将新的this.state.relativesthis.state.userName通过这些路径传递到我的“提要”组件中。 但我收到此错误消息:

警告:[反应路由器]您不能更改; 这将是   被忽略

我知道为什么会这样,但是不知道我应该如何将状态传递给我的“ feed”组件。 在过去的5个小时里,我一直在尝试解决此问题,我已变得非常绝望!

请帮忙!谢谢


解:

下面的答案是有帮助的,我要感谢athors,但是它们并不是最简单的方法。就我而言,最好的方法是:更改路线时,您只需向其添加一条消息,如下所示:

browserHistory.push({pathname: '/pathname', state: {message: "hello, im a passed message!"}});

或者如果您通过链接进行操作:

<Link 
    to={{ 
    pathname: '/pathname', 
    state: { message: 'hello, im a passed message!' } 
  }}/>

来源:[https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/location.md]

在您尝试到达的组件中,然后可以像下面这样访问变量:

  componentDidMount: function() {
    var recievedMessage = this.props.location.state.message
  },

我希望这有帮助! :)

3个解决方案
29 votes

tl; dr,最好的办法是在管理需要在整个应用程序中都可访问的状态时使用诸如<Route>或2702331924365968968之类的商店。 这些库允许您的组件连接/观察状态,并保持任何状态更改的最新状态。

什么是<Route>

您无法将道具传递给<Route>组件的原因是,就它们不会渲染任何东西而言,它们不是真正的组件。 相反,它们用于构建路由配置对象。

这意味着:

<Router history={browserHistory}>
  <Route path='/' component={App}>
    <Route path='foo' component={Foo} />
  </Route>
</Router>

等效于此:

<Router history={browserHistory} routes={{
  path: '/',
  component: App,
  childRoutes: [
    {
      path: 'foo',
      component: Foo
    }
  ]
}} />

仅在初始安装时评估路线,这就是为什么您无法将新道具传递给它们的原因。

静态道具

如果您有一些静态道具要传递给商店,则可以创建自己的高阶组件,将其注入商店。 不幸的是,这仅适用于静态道具,因为如上所述,<Route>s仅被评估一次。

function withProps(Component, props) {
  return function(matchProps) {
    return <Component {...props} {...matchProps} />
  }
}

class MyApp extends React.Component {
  render() {
    return (
      <Router history={browserHistory}>
        <Route path='/' component={App}>
          <Route path='foo' component={withProps(Foo, { test: 'ing' })} />
        </Route>
      </Router>
    )
  }
}

使用<Route>

<Route>是在导航时在组件之间传递状态的便捷方法。 但是,它有一个主要缺点,那就是该状态仅在您的应用程序中导航时才存在。 如果用户点击了指向您网站的链接,则该位置将不会附加任何状态。

使用商店

那么如何将数据传递到路线的<Route>s? 一种常见的方式是使用像component<Route>之类的商店。借助<Route path='/' component={Base}>,您可以将<Router>的组件使用更高阶的组件到商店中。 然后,当您的路线render(实际上是带有您的路线组件作为其子级的HOC)呈现时,它可以从商店中获取最新信息。

const Foo = (props) => (
  <div>{props.username}</div>
)

function mapStateToProps(state) {
  return {
    value: state.username
  };
}

export default connect(mapStateToProps)(Foo)

我对<Route>并不是特别熟悉,但是据我了解,它甚至更容易设置。 使用component<Route>或其他状态管理中的一种是在整个应用程序中传递状态的好方法。

注意:您可以在此处停止阅读。 以下是传递状态的合理示例,但您可能应该仅使用商店库。

没有商店

如果您不想使用商店怎么办? 你不走运吗? 不,但是您必须使用React的实验功能:<Route>。为了使用<Route>,您的父组件之一必须显式定义component方法和<Route>对象。 任何想要通过<Route path='/' component={Base}>访问这些值的子组件都将需要定义<Router>对象(类似于render)。

class MyApp extends React.Component {

  getChildContext() {
    return {
      username: this.state.username
    }
  }

}

MyApp.childContextTypes = {
  username: React.PropTypes.object
}

const Foo = (props, context) => (
  <div>{context.username}</div>
)

Foo.contextTypes = {
  username: React.PropTypes.object
}

您甚至可以编写自己的高阶组件,该组件会自动将2702331924365968968384值作为component <Route>的道具。 这将是一个“穷人商店”。 您可以使它正常工作,但与使用上述商店库之一相比,它最有可能效率较低且存在更多错误。

<Route>呢?

还有另一种为<Route>component提供道具的方法,但是一次只能工作一个级别。 本质上,当React Router基于当前路径渲染组件时,它将首先为最深层嵌套的匹配<Route>创建一个元素。 然后,在为下一个嵌套最深的<Router>创建元素时,它将该元素作为<Route path='/' component={Base}>传递。这意味着在第二个组件的render方法中,您可以使用React.cloneElement克隆现有的children元素并为其添加其他道具。

const Bar = (props) => (
  <div>These are my props: {JSON.stringify(props)}</div>
)

const Foo = (props) => (
  <div>
    This is my child: {
      props.children && React.cloneElement(props.children, { username: props.username })
    }
  </div>
)

这当然是乏味的,特别是如果您需要通过<Route> components的多个级别传递此信息。 您还需要在基本<Route>组件(即<Route path='/' component={Base}>)中管理您的状态,因为您无法从<Router>的父组件中注入状态。

Paul S answered 2020-01-14T13:42:08Z
1 votes

一旦安装了路由器组件,就无法更改React-router的状态。 您可以编写自己的HTML5路由组件,并监听url的更改。

class MyRouter extend React.component {
   constructor(props,context){
   super(props,context);
   this._registerHashEvent = this._registerHashEvent.bind(this)

 } 

 _registerHashEvent() {
    window.addEventListener("hashchange", this._hashHandler.bind(this), false);
  }
  ...
  ...

render(){
  return ( <div> <RouteComponent /> </div>)
}
Khalid Azam answered 2020-01-14T13:42:28Z
1 votes

我知道回答这个问题可能为时已晚,但是对于以后对此有所疑问的任何人,您都可以使用以下示例方式:

export default class Routes extends Component {
constructor(props) {
    super(props);
    this.state = { config: 'http://localhost' };
}
render() {
    return (
        <div>
            <BrowserRouter>
                <Switch>
                    <Route path="/" exact component={App} />
                    <Route path="/lectures" exact render={() => <Lectures config={this.state.config} />} />
                </Switch>
            </BrowserRouter>
        </div>
    );
}

}

这样,您就可以在Lecture组件中访问配置道具。这是一个围绕该问题的步骤,但是从一开始它就是一个不错的选择! :)

Damian Busz answered 2020-01-14T13:42:57Z
translate from https://stackoverflow.com:/questions/41466055/how-do-i-pass-state-through-react-router