在 RelayJS 和 GraphQL 中为多态关联编写片段

Writing Fragments for Polymorphic Associations in RelayJS and GraphQL

我的后端模式有一个模型,Request,它使用多态关联,这样几个不同的模型所有 have-many 请求和一个 Request 可以属于这些不同模型中的任何一个型号。

我有一个 React 组件,RequestList,我希望能够在它的任何潜在 parent 模型中使用它。

下面是一些示例代码:

FooShowView.js

class FooShowView extends Component {
  render() {
    return (
      <RequestList router={this.props.router} />
    )
  }
}

export default Relay.createContainer(ShowView, {
  initialVariables: {
    FooId: null
  },
  fragments: {
    viewer: (variables) => {
      return Relay.QL`
        fragment on Viewer {
          Foo(id: $FooId) {
            id${ RequestList.getFragment('Foo') }
          }
        }`
      `
    }
  }
});

RequestList.js

class RequestList extends Component {

  renderRows = () => {
    return this.props.requests.edges.map(edge => edge.node).map((intReq, i) => {
      return (
        <RequestRow
          request={ intReq }
          key={ i }
        />
      );
    });
  }

  render() {
    return (
      <Table>
        { this.renderRows() }
      </Table>
    );
  }
};

export default Relay.createContainer(RequestList, {
  fragments: {
    foo: () => Relay.QL`
      fragment on Foo {
        requests(first: 10) {
          edges {
            node {
              ${ RequestRow.getFragment('request') }
            }
          }
        }
      }
    `,
  }
})

问题是,现在要为 Request 的 parent 中的另一个呈现 RequestTable,比如在 BarShowView 中,我需要添加一个新片段到 RequestList:

bar: () => Relay.QL`
  fragment on Bar {
    requests(first: 10) {
      edges {
        node {
          ${ RequestRow.getFragment('request') }
        }
      }
    }
  }
`,

然后 Relay 会发出警告,提示我需要将 bar 和 foo 作为 props 提供给我的列表,即使它与当前视图无关。

由于 Request 在我的模式中与大约 8 个不同的模型相关联,这很快就会变得不合理。

创建可重用 React 组件的正确方法是什么,该组件将呈现我正在查看的任何记录的多态 children?

我最后做的(以防有人遇到这个问题)只是将 RequestList 片段放在根目录上并传入变量,因此它只查询适当的关联记录。比必须编写六个片段要简单得多。所以我的 createContainer 调用现在看起来像:

export default Relay.createContainer(RequestList, {
  initialVariables: {
    fooId: null,
    barId: null
  }
  fragments: {
    viewer: () => Relay.QL`
      fragment on Viewer {
        requests(
          first: 10,
          fooId: $fooId,
          barId: $barId
        ) {
          edges {
            node {
              ${ RequestRow.getFragment('request') }
            }
          }
        }
      }
    `,
  }
})

注意:如果你想知道为什么我放弃了 fooID 和 barId 而不是 "requestableType" 和 "requestableID",那是因为我使用的 Elixir 不支持这种类型的多态性。