Как передать данные компоненту из контейнера в роутере?

Возможно не правильно сформулировал вопрос, сейчас на пальцах объясню что имею ввиду:

Вот мой роутер:
import React from 'react'
import { Route, IndexRedirect } from 'react-router'

import App from './containers/App'
import Publication from './containers/Publication';

import NotFound from './components/NotFound'
import PublicationList from './components/PublicationList';
import PublicationForm from './components/PublicationForm';
import PublicationSetting from './components/PublicationSetting';

export const routes = (
  <div>
    <Route path='/' component={App}>
      <Route path='publications' component={Publication}>
          <IndexRedirect to='list' />
          <Route path='list' component={PublicationList} />
          <Route path='form' component={PublicationForm} />
          <Route path='setting' component={PublicationSetting} />
      </Route>
      <Route path='*' component={NotFound} />
    </Route>
  </div>
)


Внимение на контейнер "Publication" и на компонент "PublicationList".
Пользователь перешел по url /publications/list, сперва отработал естественно контейнер "Publication", где ему в this.props.children передается дочерний компонент "PublicationList".
Ествественно в "Publication" в рендере есть {this.props.children}

Теперь вопрос, при инициализации контейнера "Publication", он получает начальное состояние, Как передать нужные данные из стейта в компонент {this.props.children}(PublicationList)?

Конечно есть компоненты внутри "Publication", которым можно передать состояние напрямую в props: и все работает, но как быть с динамическими компонентами, которые подключаются в зависимости от url?

Я пока не уточнял возможно ли это, добавить роуты и в контейнер "Publication", но мне кажется это приведет к хаосу, так как удобно, когда все роуты в одном файле и ты знаешь каким компонентом/контейнером отвечает приложение.

Вообщем как то так, прошу ткнуть, так как информацию не нашел.

UPD:
Неужели придется компоненты в контейнеры переводить и для каждого из них создавать свой редьюсер, экшен, константы? это же наплодит столько файлов.

Как вы решаете данный вопрос?
  • Вопрос задан
  • 1062 просмотра
Пригласить эксперта
Ответы на вопрос 3
@Aves
https://facebook.github.io/react/docs/context можно использовать.
class Publication extends React.Component {
  state = {
    list: []
  };
  componentDidMount() {
    this.timer = setInterval(() => {
      this.setState({list: [...this.state.list, new Date().toString()]});
    }, 10000);
  }
  componentWillUnmount() {
    clearInterval(this.timer);
  }
  static childContextTypes = {
    list: React.PropTypes.array
  };
  getChildContext() {
    return {
      list: this.state.list
    };
  }
  render() {
    return (
      <div>
        <h4>Publication</h4>
        {this.props.children}
      </div>
    );
  }
}

const PublicationList = (props, context) => (
  <ul>
    {context.list.map(e => <li key={e}>{e}</li>)}
  </ul>
);
PublicationList.contextTypes = {list: React.PropTypes.array};

Вообще, не вижу, в чем сложность использовать redux, и зачем
для каждого из них создавать свой редьюсер, экшен, константы
Достаточно просто
export connect(state => ({list: state.publication.list}))(PublicationList)
Ответ написан
Комментировать
@kostiknoir
способ #1
родительский компонент явно знает что нужно дочернему компоненту и тогда родительский компонент явно передаёт нужные значения через props
Один из главных минусов: в каждом родительском компоненте нужно учитывать требования всех дочерних компонентов на всех нижележащих уровнях

способ #2
родительский компонент предполагает что дочерний компонент будет использовать что-то из его props и state (т.е. из props и state родительского компонента). Поэтому родительский компонент явно передаёт свои state и props дочернему элементу с помощью props
Минус #1 - см. способ #1
Минус #2 - состояние данного родительского компонента становится общедоступным. Что не всегда хорошо

способ #3
данные которые нужны для разных компонентов выносятся в глобальную область видимости (redux, flux, mobx и т.д.).
В этом случае родительский компонент обновляет какую-то часть общедоступных данных.
Другие компоненты, которые заинтересованы в этих данных, подписываются на уведомления об изменениях этих данных
Минус - дополнительный уровень абстракции
Но решает недостатки предыдущих вариантов

Что лучше... Зависит от ситуации
Ответ написан
@LiguidCool
Ну Redux как раз для того?

upd. v.2
  1. Почитайте как располагаются модули в React без роутера (примеров море). Допустим. есть App, в нем подключается Users. Там же в свою очередь есть 2 класса Users и User. Причем второй может быть тоже в отдельном файле. Это несколько помогает разгрузить App. Это не обязательно, но это абстрагирует App от User. Приложению и не надо знать о пользователе, только о их списке.
  2. Обратите внимание на пример в доках. Как раз очень похожая реализация как у вас. User дочерний компонент Users:
    componentDidMount() {
        this.setState({
          // route components are rendered with useful information, like URL params
          user: findUserById(this.props.params.userId)
        })

    Если же у вас "глупый" компонент, то вам никто не мешает сразу рендерить this.props.params.bla-bla
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы