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

Я ищу хороший синтаксис для передачи переменной из родительского контейнера в дочерний контейнер.

Допустим, у меня есть эти маршруты с глобальным списком виджетов на / и конкретными списками виджетов на /widgets/:WidgetListID.

Примечание. Я использую react-router-relay

<Route
    path='/' component={Layout}
  >
    <IndexRoute
      component={WidgetListContainer}
      queries={ViewerQueries}
    />
    <Route
      path='/widgets/:WidgetListID'
      component={WidgetListContainer}
      queries={ViewerQueries}
    />
  </Route>

Это тот же компонент <WidgetList/>, отрендеренный внутри <WidgetListContainer/> внутри <Layout/>, и вот как я пытаюсь передать переменную WidgetListID:

Layout.js

class Layout extends React.Component {
  render() {
    return (
      <div>
       ...
        {children}
       ...
      </div>
    );
  }
}

WidgetListContainer.js

class WidgetListContainer extends React.Component {
  render () {
    return (
      <div>
       ...
        <WidgetList 
          viewer={viewer}
        />
      </div>
    )
  }
}

export default Relay.createContainer(WidgetListContainer, {
  initialVariables: {
    WidgetListID: null
  },
  fragments: {
    viewer: ($WidgetListID) => Relay.QL`
      fragment on User {
        ${WidgetList.getFragment('viewer', $WidgetListID)}
      }
    `,
  },
})

WidgetList.js

class WidgetList extends React.Component {
  render () {
    return (
      <div>
        <ul>
          {viewer.widgets.edges.map(edge =>
            <li key={edge.node.id}>{edge.node.widget.name}</li>
          )}
        </ul>
      </div>
    )
  }
}
export default Relay.createContainer(WidgetList, {
  initialVariables: {
    WidgetListID: null
  },
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
         widgets(first: 10, WidgetListID:$WidgetListID) { 
          edges { 
            node { 
              id, 
              name
            } 
          } 
        } 
      }
    `,
  },
})

У меня нет проблем с установкой переменной WidgetListID непосредственно внутри релейного контейнера WidgetList, она отлично работает, но как только я пытаюсь передать ее из релейного контейнера WidgetListContainer, у меня появляется пустой объект данных {__dataID__: "VXNlcjo="}. Тем не менее, переменная хорошо напечатана в моей функции getWidget(). Так что-то не работает в какой-то момент, но я не могу понять, что?

Каков был бы хороший синтаксис для передачи переменной WidgetListID из родительского контейнера в дочерний контейнер?


person Victorien    schedule 24.09.2015    source источник


Ответы (2)


В WidgetListContainer измените это:

fragments: {
    viewer: ($WidgetListID) => Relay.QL`
      fragment on User {
        ${WidgetList.getFragment('viewer', $WidgetListID)}
      }
    `,
  },

to

fragments: {
    viewer: ({WidgetListID}) => Relay.QL`
      fragment on User {
        ${WidgetList.getFragment('viewer', {WidgetListID})}
      }
    `,
  },

Первым аргументом построителя фрагментов является реле variables. Итак, сначала вам нужно вытащить переменную WidgetListID из переменных WidgetListContainer, а затем вы можете передать ее в WidgetList.getFragment().

Обратите внимание, что символ $ используется только внутри строки шаблона Relay.QL. Внутри объекта переменных вы обращаетесь к переменной по имени, без $.

person sefnap    schedule 24.09.2015
comment
Спасибо за ваш ответ! Кажется, я снова что-то упускаю, у меня теперь ошибка: RelayFragmentReference: Variable 'WidgetListID' is undefined in fragment 'WidgetList'.? - person Victorien; 25.09.2015
comment
Извиняюсь; Я сделал ошибку в вызове getFragment; вам также нужно передать route. Итак, должно быть WidgetList.getFragment('viewer', route, {WidgetListID}). Я обновил ответ, так что, надеюсь, на этот раз он сработает :) - person sefnap; 25.09.2015
comment
Хм... Извините, но похоже мой ответ неверен. В конце концов, это не работает, как я ожидал. :( - person sefnap; 25.09.2015
comment
Нет, не работает :( В любом случае спасибо за помощь! Я буду продолжать попытки... Я дам вам знать. - person Victorien; 25.09.2015
comment
Просто чтобы продолжить, лучшее, что я мог придумать, - это передать значение в реквизиты дочернего компонента и заставить дочерний элемент установить переменную со значением. - person sefnap; 27.09.2015
comment
Да, я тоже так делал, но понял, что компонент отрисовывался два раза: первый раз с переменной как null и второй раз с переданной переменной. Наконец, я просто запрашиваю данные в WidgetListContainer и передаю их в качестве реквизита для widgetList. Я сказал себе, что если я не могу передать переменную, значит, я передам все данные. Почему бы и нет? - person Victorien; 28.09.2015
comment
Этот ответ был очень близок. Я отредактировал его. Можете ли вы попробовать еще раз и принять это, если это сработает @Victorien? - person steveluscher; 05.12.2015

Привет, я тоже немного боролся с этим. Измените это:

 class WidgetListContainer extends React.Component {
  render () {
    return (
      <div>
       ...
        <WidgetList 
          viewer={viewer}
        />
      </div>
    )
  }
 }

к этому:

class WidgetListContainer extends React.Component {
  render () {
    return (
      <div>
       ...
       <WidgetList
          WidgetListID={this.props.relay.variables.WidgetListID}
          viewer={viewer}
        />
      </div>
    )
  }
}

также в контейнере реле вашего компонента WidgetList не забудьте установить начальные переменные в initialVariables: { WidgetListID: null }, эта настройка сделает вашу переменную WidgetListID доступной для контейнера реле вашего компонента WidgetList.

person Ilyas Talgatuly Malgazhdarov    schedule 27.09.2015
comment
о, и не забудьте об изменении в предыдущем ответе - person Ilyas Talgatuly Malgazhdarov; 27.09.2015
comment
Спасибо за ваш ответ, я тоже пробовал, но у меня та же проблема, пустой объект данных {__dataID__: "VXNlcjo="}. Может у меня проблема в другом? Я не понимаю, потому что, если я инициализирую переменную любой строкой, она работает. У меня есть эта проблема только при попытке передать переменную, поэтому я сказал себе, что проблема была там, а может быть, и нет? - person Victorien; 28.09.2015