我如何通过React_router传递状态? [英] How do i pass state through React_router?

查看:62
本文介绍了我如何通过React_router传递状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是引起我麻烦的文件:

Here is the file that's causing me trouble:

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.relatives this.state.userName 通过路由进入我的提要组件。但是我收到此错误消息:

I am trying to pass the new this.state.relatives and this.state.userName through the routes into my "feed"-component. But I'm getting this error message:


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

Warning: [react-router] You cannot change ; it will be ignored

我知道为什么会这样,但是不知道我应该怎么过我的 Feed组件的状态。在过去的5个小时中,我一直在尝试解决此问题,而且我已经变得非常绝望!

I know why this happens, but don't know how else i'm supposed to pass the states to my "feed"-component. I've been trying to fix this problem for the past 5 hours and í'm getting quite desperate!

请帮助!
谢谢

Please help! Thanks

答案下面的内容很有帮助,我要感谢athors,但这并不是最简单的方法。
在我的情况下,最好的方法是这样:
更改路线时,您只需将一条消息附加如下:

The answers below were helpful and i thank the athors, but they were not the easiest way to do this. The best way to do it in my case turned out to be this: When you change routes you just attach a message to it like this:

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

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

or if you do it through a link:

<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

在您要访问的组件中,您可以像下面这样访问变量:

In the component you are trying to reach you can then access the variable like this for example:

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

我希望这会有所帮助! :)

I hope this helps! :)

推荐答案

tl; dr 最好的选择是使用<$ c $这样的商店c> redux 或 mobx 在管理需要在整个应用程序中访问的状态时。这些库允许您的组件连接/观察状态,并随时了解任何状态更改。

tl;dr your best bet is to use a store like redux or mobx when managing state that needs to be accessible throughout your application. Those libraries allow your components to connect to/observe the state and be kept up to date of any state changes.

无法通过< Route> 组件传递道具的原因从某种意义上说,它们不是真正的组件,因为它们不会渲染任何东西。而是使用它们来构建路由配置对象。

The reason that you cannot pass props through <Route> components is that they are not real components in the sense that they do not render anything. Instead, they are used to build a route configuration object.

这意味着:

<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
    }
  ]
}} />

仅在初始坐骑时评估路线,这就是为什么您不能将新道具传递给他们的原因。

The routes are only evaluated on the initial mount, which is why you cannot pass new props to them.

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

If you have some static props that you want to pass to your store, you can create your own higher order component that will inject them into the store. Unfortunately, this only works for static props because, as stated above, the <Route>s are only evaluated once.

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>
    )
  }
}



使用 location.state



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

Using location.state

location.state is a convenient way to pass state between components when you are navigating. It has one major downside, however, which is that the state only exists when navigating within your application. If a user follows a link to your website, there will be no state attached to the location.

那么如何将数据传递到路线的组件?一种常见的方式是使用 redux mobx 之类的商店。使用 redux ,您可以使用更高阶的组件连接到商店。然后,当您的路线的组件(实际上是将您的路线组件作为其子组件的HOC)呈现时,它可以从商店中获取最新信息。

So how do you pass data to your route's components? A common way is to use a store like redux or mobx. With redux, you can connect your component to the store using a higher order component. Then, when your route's component (which is really the HOC with your route component as its child) renders, it can grab up to date information from the store.

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

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

export default connect(mapStateToProps)(Foo)

我对 mobx 并不特别熟悉,但是据我所知,它甚至更容易设置。使用 redux mobx 或其他状态管理之一是在整个应用程序中传递状态的好方法。 / p>

I am not particularly familiar with mobx, but from my understanding it can be even easier to setup. Using redux, mobx, or one of the other state management is a great way to pass state throughout your application.


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

Note: You can stop reading here. Below are plausible examples for passing state, but you should probably just use a store library.



没有商店



如果您不想使用商店怎么办?你不走运吗?不,但是您必须使用React的实验功能 上下文 。为了使用上下文,您的父组件之一必须显式定义 getChildContext 方法以及 childContextTypes 对象。任何想要通过 context 访问这些值的子组件都需要定义一个 contextTypes 对象(类似于 propTypes )。

Without A Store

What if you don't want to use a store? Are you out of luck? No, but you have to use an experimental feature of React: the context. In order to use the context, one of your parent components has to explicitly define a getChildContext method as well as a childContextTypes object. Any child component that wants to access these values through the context would then need to define a contextTypes object (similar to propTypes).

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
}

您甚至可以编写自己的高阶组件来自动注入 context 值作为< Route> 组件的道具。这将是一个穷人商店。您可以使用它,但与使用上述存储库之一相比,它效率可能更高,并且存在更多的错误。

You could even write your own higher order component that automatically injects the context values as props of your <Route> components. This would be something of a "poor man's store". You could get it to work, but most likely less efficiently and with more bugs than using one of the aforementioned store libraries.

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

There is another way to provide props to a <Route>'s component, but it only works one level at a time. Essentially, when React Router is rendering components based on the current route, it creates an element for the most deeply nested matched <Route> first. It then passes that element as the children prop when creating an element for the next most deeply nested <Route>. That means that in the render method of the second component, you can use React.cloneElement to clone the existing children element and add additional props to it.

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> 组件的多个级别传递此信息。您还需要在基本的< Route> 组件中管理状态(即< Route path ='/'component = {Base} > ),因为您将无法从< Router> 的父组件注入状态。

This is of course tedious, especially if you were to need to pass this information through multiple levels of <Route> components. You would also need to manage your state within your base <Route> component (i.e. <Route path='/' component={Base}>) because you wouldn't have a way to inject the state from parent components of the <Router>.

这篇关于我如何通过React_router传递状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆