Reputation: 15239
I have a Parent component which contains many Child components as an array. Each child component contains a huge amount of data. So, I decided to not load all of them when Parent get loaded. The data fetched from Parent container is as following:
{
...
childs: [childId1, childId2, ...] // Array of child id
...
}
Then, I would like to send one request per child by passing the child's id to back-end apis. Each child will be show up on the UI whenever its data get back, otherwise, a spinner icon is displayed for indicating the loading data.
Would it be possible to achieve this in Relay?
UPDATED:
Here is an example of the option 1:
Child container:
export default Relay.createContainer(Child, {
initialVariables: {
id: null,
hasQuery: false
},
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
child(id: $id) @include(if: $hasQuery) {
...
}
}
`,
},
});
Child component:
const Child = React.createClass({
componentWillMount() {
ChildContainer.setVariables({ id: this.props.childId, hasQuery: true });
}
});
Parent container:
export default Relay.createContainer(Parent, {
fragments: {
viewer: () => Relay.QL`
fragment on Viewer {
childIds // Return an array of child's id
Child.getFragment('viewer')
}
`,
},
});
Parent component:
const Parent = React.createClass({
render() {
this.props.viewer.childIds.map(childId => {
<Child childId={childId} />
});
}
});
The problem is that when each Child got rendered, it fetched its data and replaced the last Child data with its own data. For example, if childIds = [1, 2, 3], it displayed data of 3 three times on the screen; 3 3 3
Upvotes: 3
Views: 1756
Reputation: 1487
There are two typical patterns for delayed data fetching in open-source Relay:
@include
or @skip
directives where the condition is initially set to false. After the UI loads, or in response to user action, set the condition to true (e.g. with setVariables
). <Relay.Renderer>
components. The top-level <RelayRenderer>
would fetch the minimum "required" data in one round trip and then display it, which would render additional <RelayRenderer>
s that would fetch more data. The second option seems best-suited to your use case: the top-level renderer would fetch the list of IDs only. Then it would render a list of UI components, each of which fetched more data about its ID. List items would render as their data resolves.
One potential downside of this approach is that the data for all the items will be fetched in parallel; the first item in the list won't necessarily be the first one to get its data and render. To mitigate this an application would have to maintain greater control of the ordering of fetches; Relay accommodates this via an 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 which implements some of these ideas and supports pluggable middleware to help achieve the rest.
Upvotes: 8