是否可以在 Relay 中进行延迟加载?
Would it be possible to do lazy loading in Relay?
我有一个 Parent 组件,其中包含许多 Child 组件作为数组。每个 child 组件都包含大量数据。因此,我决定在 Parent 加载时不加载所有这些。从Parent容器中获取的数据如下:
{
...
childs: [childId1, childId2, ...] // Array of child id
...
}
然后,我想通过将 child 的 ID 传递给 back-end api 来为每个 child 发送一个请求。每个 child 将在其数据返回时显示在 UI 上,否则,将显示一个微调器图标以指示加载数据。
是否可以在 Relay 中实现?
更新:
这是选项 1 的示例:
Child 容器:
export default Relay.createContainer(Child, {
initialVariables: {
id: null,
hasQuery: false
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
child(id: $id) @include(if: $hasQuery) {
...
}
}
`,
},
});
Child分量:
const Child = React.createClass({
componentWillMount() {
ChildContainer.setVariables({ id: this.props.childId, hasQuery: true });
}
});
Parent容器:
export default Relay.createContainer(Parent, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
childIds // Return an array of child's id
Child.getFragment('viewer')
}
`,
},
});
Parent分量:
const Parent = React.createClass({
render() {
this.props.viewer.childIds.map(childId => {
<Child childId={childId} />
});
}
});
问题在于,当每个 Child 被渲染时,它会获取其数据并将最后一个 Child 数据替换为自己的数据。例如childIds = [1, 2, 3],则在屏幕上显示3次数据; 3 3 3
开源Relay延迟取数据有两种典型模式:
- 使用
@include
或 @skip
指令,其中条件最初设置为 false。在 UI 加载后,或响应用户操作,将条件设置为真(例如 setVariables
)。
- 使用嵌套的
<Relay.Renderer>
组件。顶级 <RelayRenderer>
将在一次往返中获取最少的 "required" 数据,然后显示它,这将呈现额外的 <RelayRenderer>
以获取更多数据。
第二个选项似乎最适合您的用例:顶级呈现器将仅获取 ID 列表。然后它将呈现 UI 个组件的列表,每个组件都获取更多关于其 ID 的数据。列表项将在其数据解析时呈现。
这种方法的一个潜在缺点是所有项目的数据将被并行获取;列表中的第一项不一定是第一个获取数据和呈现的项目。为了缓解这种情况,应用程序必须保持对获取顺序的更大控制; Relay 通过 injectable network layer. For example, you could batch requests to the server and/or ensure ordering (for example by intentionally delaying resolving responses of "later" requests until previous queries have completed). You might check out the community-driven react-relay-network-layer 实现了其中一些想法并支持可插入中间件以帮助实现其余部分。
我有一个 Parent 组件,其中包含许多 Child 组件作为数组。每个 child 组件都包含大量数据。因此,我决定在 Parent 加载时不加载所有这些。从Parent容器中获取的数据如下:
{
...
childs: [childId1, childId2, ...] // Array of child id
...
}
然后,我想通过将 child 的 ID 传递给 back-end api 来为每个 child 发送一个请求。每个 child 将在其数据返回时显示在 UI 上,否则,将显示一个微调器图标以指示加载数据。
是否可以在 Relay 中实现?
更新:
这是选项 1 的示例:
Child 容器:
export default Relay.createContainer(Child, {
initialVariables: {
id: null,
hasQuery: false
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
child(id: $id) @include(if: $hasQuery) {
...
}
}
`,
},
});
Child分量:
const Child = React.createClass({
componentWillMount() {
ChildContainer.setVariables({ id: this.props.childId, hasQuery: true });
}
});
Parent容器:
export default Relay.createContainer(Parent, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
childIds // Return an array of child's id
Child.getFragment('viewer')
}
`,
},
});
Parent分量:
const Parent = React.createClass({
render() {
this.props.viewer.childIds.map(childId => {
<Child childId={childId} />
});
}
});
问题在于,当每个 Child 被渲染时,它会获取其数据并将最后一个 Child 数据替换为自己的数据。例如childIds = [1, 2, 3],则在屏幕上显示3次数据; 3 3 3
开源Relay延迟取数据有两种典型模式:
- 使用
@include
或@skip
指令,其中条件最初设置为 false。在 UI 加载后,或响应用户操作,将条件设置为真(例如setVariables
)。 - 使用嵌套的
<Relay.Renderer>
组件。顶级<RelayRenderer>
将在一次往返中获取最少的 "required" 数据,然后显示它,这将呈现额外的<RelayRenderer>
以获取更多数据。
第二个选项似乎最适合您的用例:顶级呈现器将仅获取 ID 列表。然后它将呈现 UI 个组件的列表,每个组件都获取更多关于其 ID 的数据。列表项将在其数据解析时呈现。
这种方法的一个潜在缺点是所有项目的数据将被并行获取;列表中的第一项不一定是第一个获取数据和呈现的项目。为了缓解这种情况,应用程序必须保持对获取顺序的更大控制; Relay 通过 injectable network layer. For example, you could batch requests to the server and/or ensure ordering (for example by intentionally delaying resolving responses of "later" requests until previous queries have completed). You might check out the community-driven react-relay-network-layer 实现了其中一些想法并支持可插入中间件以帮助实现其余部分。