在 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 不支持这种类型的多态性。
我的后端模式有一个模型,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 不支持这种类型的多态性。