是否可以在 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延迟取数据有两种典型模式:

  1. 使用 @include@skip 指令,其中条件最初设置为 false。在 UI 加载后,或响应用户操作,将条件设置为真(例如 setVariables)。
  2. 使用嵌套的 <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 实现了其中一些想法并支持可插入中间件以帮助实现其余部分。