【问题标题】:How to wire data to a deep component in react-router-relay?如何将数据连接到 react-router-relay 中的深层组件?
【发布时间】:2017-07-27 21:41:44
【问题描述】:

我有这样的路线

<Route path="/search" component={Search}>

基本的Search 组件看起来像这样

class Search extends React.Component {
  constructor (props) {
    super(props)
    this.state = {query: ''}
  }
  handleSubmit (event) {
    event.preventDefault()
    this.setState({query: this.refs.queryInput.value})
  }
  renderSearchResult() {
    if (this.state.query === '')
      return <EmptySearchResult />
    else
      return <SearchResult query={this.state.query}/>
  }
  render() {
    return (
      <div className="searchContainer">
        <div className="row">
          <div className="search">
            <form onSubmit={event => this.handleSubmit(event)}>
              <input className="searchInput" placeholder="robocop" ref="queryInput" />
            </form>
          </div>
        </div>
        <div className="row">
          {this.renderSearchResult()}
        </div>
      </div>
    )
  }
}

SearchResult中继容器长这样

class SearchResult extends React.Component {
  render() {
    var {viewer: {moviesByTitle: movies}} = this.props;
    return (
      <div className="searchResult">
        {movies.edges.map((edge,i) =>
          <div key={i} className="rowItem scrollRowItem">
            <Movie movie={edge.node} />
          </div>)}
      </div>
    )
  }
}

export default Relay.createContainer(SearchResult, {
  initialVariables: {
    query: '???'
  },
  fragments: {
    viewer: () => Relay.QL`
      fragment on User {
        moviesByTitle(title: $query, first: 10) {
          edges {
            node {
              ${Movie.getFragment('movie')}
            }
          }
        }
      }
    `
  }
})

错误:

Warning: RelayContainer: Expected prop `viewer` to be supplied to `SearchResult`, but got `undefined`. Pass an explicit `null` if this is intentional.

我在搜索组件中尝试做的事情(更改为粗体)

const ViewerQueries = {
  viewer: () => Relay.QL`query { viewer }`
}

...

renderSearchResult() {
  if (this.state.query === '')
    return <EmptySearchResult />
  else
    return <SearchResult query={this.state.query} queries={ViewerQueries} />
}

但这当然行不通,因为查询需要以某种方式附加到Route


问题

  1. 我的Search 组件只是一个展示组件,不需要自己的数据。相反,它只是将 query 属性提供给 SearchResult 中继容器。我应该如何构建组件和中继容器以正确地将它们附加到路由?

  2. 如何使用SearchResult query 属性在中继查询片段中设置变量?

  3. 我一般不理解“查看器”抽象——我见过的大多数示例都非常人为,并没有显示它们在更现实的环境中如何工作;例如,对不同资源具有不同访问权限的用户,或旨在查看不同数据片段的程序的不同部分

【问题讨论】:

  • 可能的答案:请注意这个问题的年龄;如果 Relay API 发生了变化,请帮助我了解最新情况
  • 我建议您看看 Facebook 上的 reactjs.orgfacebook.github.io/relay,如果您确实获得了您错过的空闲时间。希望这会有所帮助。

标签: functional-programming react-router graphql relay react-router-relay


【解决方案1】:

使用 Relay 的现代 API,从 SearchResult 组件组成一个 refetchContainer,因为需要 “使用不同变量执行新查询并在请求返回时呈现该查询的响应的选项” .

import React, { Component } from 'react';
import debounce from 'debounce';
import { graphql, createRefetchContainer } from 'react-relay';

class SearchResult extends React.Component {
  componentWillReceiveProps(nextProps) {
    if (this.props.query != nextProps.query) {
      debounce(() => this._searchMovies(), 600);
    }
  }

  _searchMovies() {
    const refetchVariables = fragmentVariables => ({
      query: this.props.query
  });

    this.props.relay.refetch(refetchVariables, null);
  }

  render() {
    var { viewer: { moviesByTitle: movies } } = this.props;
    return (
      <div className="searchResult">
        {movies.edges.map((edge, i) =>
          <div key={i} className="rowItem scrollRowItem">
            <Movie movie={edge.node} />
          </div>)}
      </div>
    )
  }
}


// Similar query syntax as Relay Classic
// Only syntactic difference is with absence of Movie.getFragment
module.exports = createRefetchContainer(SearchResult, {
    viewer: graphql`
      fragment SearchResult_viewer on SearchResult {
        @argumentDefinitions(
          query: {type: "String", defaultValue: ""}
        ) {
        moviesByTitle(title: $query, first: 10) {
          edges {
            node {
              ...Movie_movie
            }
          }
        }
      }`
    },
    graphql`
      query MoviesRefetchQuery($query: String) {
        viewer {
          ...SearchResult_viewer @arguments(query: $query)
        }
      }
   `);

【讨论】:

    猜你喜欢
    • 2017-11-01
    • 1970-01-01
    • 2020-11-18
    • 2018-01-10
    • 2015-12-27
    • 2018-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多