简体   繁体   English

中继片段变量

[英]Relay fragment variables

Link Github issue: https://github.com/facebook/relay/issues/1218 链接Github问题: https //github.com/facebook/relay/issues/1218

We have encountered an strange behaviour of Relay. 我们遇到了Relay的奇怪行为。 I will try to explain the best I can. 我会尽力解释我能做的最好的事情。

So we have an "main" relay container that fetches the data for corresponding store, and also includes and fragment from Ticket container. 因此,我们有一个“主”中继容器,用于获取相应商店的数据,还包括Ticket容器和片段。 Ticket container render out custom table that has filter and sorting. 故障单容器呈现具有过滤和排序的自定义表。 So you can see that in StoreFrom component StoreTicketList container is import all required props are passed like Store fragment. 所以你可以看到StoreFrom组件中的StoreTicketList容器导入所有必需的道具都像Store片段一样传递。

The problem occurs when you try to filter StoreList Ticket, I mean set filter or sort relay variables. 当您尝试过滤StoreList Ticket时会出现问题,我的意思是设置过滤器或排序中继变量。 You will get this error: 你会收到这个错误:

Warning: RelayContainer: component TicketList was rendered with variables that differ from the variables used to fetch fragment Store . 警告:RelayContainer:组件TicketList使用的变量与用于获取片段Store的变量不同。 The fragment was fetched with variables {"first":5,"after":null,"last":null,"before":null,"sort":null,"filter":null} , but rendered with variables {"first":5,"after":null,"last":null,"before":null,"sort":null,"filter":{"authorAccount":{"email":{"__e":"wrongEmail@email.com"}}}} . 该片段使用变量{"first":5,"after":null,"last":null,"before":null,"sort":null,"filter":null} ,但使用变量{"first":5,"after":null,"last":null,"before":null,"sort":null,"filter":{"authorAccount":{"email":{"__e":"wrongEmail@email.com"}}}}渲染{"first":5,"after":null,"last":null,"before":null,"sort":null,"filter":{"authorAccount":{"email":{"__e":"wrongEmail@email.com"}}}} This can indicate one of two possibilities: - The parent set the correct variables in the query - TicketList.getFragment('Store', {...}) - but did not pass the same variables when rendering the component. 这可以指示两种可能性之一: - 父级在查询中设置正确的变量 - TicketList.getFragment('Store', {...}) - 但在渲染组件时没有传递相同的变量。 Be sure to tell the component what variables to use by passing them as props: <TicketList ... first={...} after={...} last={...} before={...} sort={...} filter={...} /> . 请务必告诉组件将哪些变量用作道具:? <TicketList ... first={...} after={...} last={...} before={...} sort={...} filter={...} /> - You are intentionally passing fake data to this component, in which case ignore this warning. - 您故意将虚假数据传递给此组件,在这种情况下忽略此警告。

But those filter/sort variables are on StoreTicketList and they arent passed dow from parent to child container like in this case Store container to StoreListTicket container. 但是那些过滤器/排序变量在StoreTicketList上并且它们不会从父容器传递到子容器,就像在这种情况下将容器存储到StoreListTicket容器一样。

export class StoreForm extends React.Component {

  constructor(props) {
    super(props);

    const { Viewer: { store } } = props;

    this.state = {
      number: store && store.number !== null ? store.number : '',
    };
  }

  handleInsert = (model) => {
    console.log('Form mutation model : ', model);
  };

  render() {
    const { Viewer, relay: { variables: { update } } } = this.props;
    return (
      <div>
        <Form>
          <FormTitle title='Store Info' />
          <FormBody>
            <TextField
              required
              fullWidth
              name='number'
              value={this.state.number}
              floatingLabelText='Number'
            />
            <StoreTicketList Store={this.props.Viewer.store} />
          </FormBody>
        </Form>
      </div>
    );
  }
}

StoreForm container (main container): StoreForm容器(主容器):

export default Relay.createContainer(StoreForm, {
  initialVariables: {
    id: null,
    update: false
  },
  prepareVariables({ id = null }) {
    return { id, update: (id !== null) };
  },
    fragments: {
        Viewer: (variables) => Relay.QL`
      fragment on Viewer {
        store(id: $id) @include(if: $update) {
          id,
          number
          ${StoreTIcketList.getFragment('Store')}
        }
      }
    `
    }
});

Ticket container: 票务容器:

export const StoreTicketList = Relay.createContainer(TicketList, {
  initialVariables: {
    first: 5,
    after: null,
    last: null,
    before: null,
    sort: null,
    filter: null
  },
    fragments: {
        Store: () => Relay.QL`
      fragment on Store {
        ticketConnection(first: $first, after: $after, last: $last, before: $before, sort: $sort, filter: $filter) {
          count,
          pageInfo {
            hasNextPage,
            hasPreviousPage,
            startCursor,
            endCursor
          },
          edges{
            node{
              created,
              subject
            }
          }
        }
      }
    `
    }
});

We have built our own Connection Table HOC component that renders table for each container. 我们已经构建了自己的连接表HOC组件,为每个容器呈现表。 In this component there are also sort and filter function that are using this.props.relay.setVariables() . 在这个组件中,还有使用this.props.relay.setVariables() sort和filter函数。 So the StoreListTicket is rendering as an ConnectionTable and it passes down the relay prop object, and if user clicks on a table colum header, component is generating an array of sort objects. 因此,StoreListTicket呈现为ConnectionTable,它向下传递中继prop对象,如果用户单击表colum头,组件将生成一个排序对象数组。

function connectionTableHOC(ComposedComponent) {

  class EnhanceTable extends React.Component {

    constructor(props) {
     super(props);
    }

    sortHandler = (sortArray) => {
     const { relay, relay: { variables } } = this.props;

     relay.setVariables({
       first: variables.first || variables.last,
       after: null,
       last: null,
       before: null,
       sort: sortArray
     });
   };

   filterHandler = (filterObj) => {
     const { relay, relay: { variables } } = this.props;

     relay.setVariables({
      first: variables.first || variables.last,
      after: null,
      last: null,
      before: null,
      filter: filterObj
    });
  };

  render() {
    return <ComposedComponent {...this.props} />;
  }
}

It turns out you need to do two things: 事实证明你需要做件事:

First, pass the props into the component, as described by Joe Savona. 首先,将道具传递到组件中,如Joe Savona所述。 I'm using react-relay-router, so for me that was a matter of adding this line 我正在使用react-relay-router,所以对我来说这是添加这一行的问题

<Route path="interviews">
  <IndexRoute component={InterviewsList} queries={ViewerQuery} />
  <Route path=":id" component={InterviewSession} queries={NodeViewerQuery}
    render={({ props }) => props ? <InterviewSession {...props} /> : <Loading />}/> // <--- this line
</Route>

Second, you must inject the variable's values into the getFragment function call, like so: 其次,必须将变量的值注入getFragment函数调用,如下所示:

fragments: {
    Viewer: (variables) => Relay.QL`
  fragment on Viewer {
    store(id: $id) @include(if: $update) {
      id,
      number
      ${StoreTIcketList.getFragment('Store', {... variables})} // <---- this thing!
    }
  }
`
}

Note that if you're using getFragment inside of your root query, variables will be argument number two: 请注意,如果您在根查询中使用getFragment ,则variables将是参数2:

const NodeViewerQuery = {
  node: (component, variables) => Relay.QL`query { // <---- extra "component" argument
    node(id: $id) {
      ${component.getFragment('node', {...variables})}
    }
  }`,

(This answer crossposted from https://github.com/facebook/relay/issues/1218 ) (这个答案来自https://github.com/facebook/relay/issues/1218

It looks like the parent component (the EnhanceTable ) is setting the variables for its child (the StoreTicketList ). 它看起来像父组件(在EnhanceTable )是设置变量的孩子(的StoreTicketList )。 This means that when the child renders it tries to render using the default variables, while the parent has fetched a different set of variables (sorted/filtered). 这意味着当子渲染时它尝试使用默认变量进行渲染,而父进程则获取了一组不同的变量(已排序/已过滤)。 The solution is to have EnhanceTable tell the rendered component what sort/filter it is using: 解决方案是让EnhanceTable告诉渲染的组件它使用的排序/过滤器:

function connectionTableHOC(ComposedComponent) {

  class EnhanceTable extends React.Component {
    ...

    render() {
      return (
        <ComposedComponent 
          {...this.props} 
          filterVarName={filterValue}
          sortVarName={sortValue}
        />
      );
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM