Подтвердить что ты не робот

Как передать состояние через 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.relatives и this.state.userName через маршруты в свой "feed" -компонент. Но я получаю сообщение об ошибке:

Предупреждение: [реактивный маршрутизатор] Вы не можете изменить; это будет игнорируется

Я знаю, почему это происходит, но не знаю, как еще я должен передавать состояния в свой "фид" -компонент. Я пытался исправить эту проблему за последние 5 часов, и я очень отчаялся!

Пожалуйста, помогите! Благодаря


РЕШЕНИЕ:

Ответы ниже были полезными, и я благодарен атестам, но они не были самым простым способом сделать это. Лучший способ сделать это в моем случае оказался таким: Когда вы меняете маршруты, вы просто присоединяете к нему сообщение:

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

Надеюсь, это поможет!:)

4b9b3361

Ответ 1

tl; dr лучше всего использовать хранилище типа redux или mobx при управлении состоянием, которое должно быть доступно во всех приложениях. Эти библиотеки позволяют вашим компонентам подключаться/следить за состоянием и постоянно обновлять любые изменения состояния.

Что такое <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> оцениваются только один раз.

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 - удобный способ передачи состояния между компонентами при навигации. Однако у него есть один существенный недостаток, заключающийся в том, что государство существует только при навигации по вашей заявке. Если пользователь следит за ссылкой на ваш сайт, государство не будет прикреплено к местоположению.

Использование магазина

Итак, как вы передаете данные на ваш маршрут component s? Обычный способ - использовать хранилище типа redux или mobx. С помощью redux вы можете connect добавить свой компонент в хранилище, используя компонент более высокого порядка. Затем, когда ваш маршрут component (который является действительно HOC с вашим компонентом маршрута в качестве его дочернего элемента), он может получить последнюю информацию из магазина.

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

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

export default connect(mapStateToProps)(Foo)

Я не особенно знаком с mobx, но, по моему мнению, его еще проще настроить. Использование redux, mobx или одно из других состояний управления - отличный способ передать состояние во всем приложении.

Примечание. Здесь вы можете прекратить чтение. Ниже приведены вероятные примеры для передачи состояния, но вы, вероятно, должны просто использовать библиотеку хранилища.

Без магазина

Что делать, если вы не хотите использовать магазин? Вам не повезло? Нет, но вы должны использовать экспериментальную функцию для React: context. Чтобы использовать context, один из ваших родительских компонентов должен явно определить метод getChildContext, а также объект childContextTypes. Любой дочерний компонент, который хочет получить доступ к этим значениям через context, тогда должен будет определить объект contextTypes (аналогичный 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> component s. Это будет что-то вроде "магазина бедных людей". Вы можете заставить его работать, но, скорее всего, менее эффективно и с большим количеством ошибок, чем с использованием одной из вышеупомянутых библиотек магазинов.

Как насчет React.cloneElement?

Существует еще один способ предоставить реквизиты <Route> component, но он работает только на одном уровне за раз. По сути, когда React Router обрабатывает компоненты на основе текущего маршрута, он сначала создает элемент для наиболее глубоко вложенного совпадающего <Route>. Затем он передает этот элемент в качестве children prop при создании элемента для следующего наиболее глубоко вложенного <Route>. Это означает, что в методе 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> component s. Вам также необходимо будет управлять своим состоянием в базовом компоненте <Route> (т.е. <Route path='/' component={Base}>), потому что у вас не было бы способа ввести состояние из исходных компонентов <Router>.

Ответ 2

вы не можете изменить состояние 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> <RouteComponet /> </div>)
}