Skip to content

Commit be45692

Browse files
yuzhiFacebook Github Bot 3
authored andcommitted
Write linked ids before traversing plural linked fields
Reviewed By: blairvanderhoof, josephsavona Differential Revision: D3713253 fbshipit-source-id: 7ec9a83a6941688f509535186d31a7a360fee746
1 parent bb38793 commit be45692

File tree

4 files changed

+119
-9
lines changed

4 files changed

+119
-9
lines changed

scripts/jest/testschema.graphql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,8 @@ type PhotoStory implements FeedUnit Node {
498498
}
499499

500500
type Story implements FeedUnit Node {
501+
attachments: [StoryAttachment]
502+
501503
# FeedUnit
502504
canViewerDelete: Boolean
503505
seenState: String
@@ -540,6 +542,11 @@ type Story implements FeedUnit Node {
540542
viewerSavedState: String
541543
}
542544

545+
type StoryAttachment {
546+
target: Story
547+
styleList: [String]
548+
}
549+
543550
type StreetAddress {
544551
city: String
545552
country: String

scripts/jest/testschema.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,22 @@
591591
"name": "Story",
592592
"description": null,
593593
"fields": [
594+
{
595+
"name": "attachments",
596+
"description": null,
597+
"args": [],
598+
"type": {
599+
"kind": "LIST",
600+
"name": null,
601+
"ofType": {
602+
"kind": "OBJECT",
603+
"name": "StoryAttachment",
604+
"ofType": null
605+
}
606+
},
607+
"isDeprecated": false,
608+
"deprecationReason": null
609+
},
594610
{
595611
"name": "canViewerDelete",
596612
"description": null,
@@ -6297,6 +6313,45 @@
62976313
"enumValues": null,
62986314
"possibleTypes": null
62996315
},
6316+
{
6317+
"kind": "OBJECT",
6318+
"name": "StoryAttachment",
6319+
"description": null,
6320+
"fields": [
6321+
{
6322+
"name": "target",
6323+
"description": null,
6324+
"args": [],
6325+
"type": {
6326+
"kind": "OBJECT",
6327+
"name": "Story",
6328+
"ofType": null
6329+
},
6330+
"isDeprecated": false,
6331+
"deprecationReason": null
6332+
},
6333+
{
6334+
"name": "styleList",
6335+
"description": null,
6336+
"args": [],
6337+
"type": {
6338+
"kind": "LIST",
6339+
"name": null,
6340+
"ofType": {
6341+
"kind": "SCALAR",
6342+
"name": "String",
6343+
"ofType": null
6344+
}
6345+
},
6346+
"isDeprecated": false,
6347+
"deprecationReason": null
6348+
}
6349+
],
6350+
"inputFields": null,
6351+
"interfaces": [],
6352+
"enumValues": null,
6353+
"possibleTypes": null
6354+
},
63006355
{
63016356
"kind": "OBJECT",
63026357
"name": "FakeNode",

src/store/RelayQueryWriter.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ class RelayQueryWriter extends RelayQueryVisitor<WriterState> {
595595

596596
const prevLinkedIDs = this._store.getLinkedRecordIDs(recordID, storageKey);
597597
const nextLinkedIDs = [];
598+
const nextRecords = {};
598599
let isUpdate = false;
599600
let nextIndex = 0;
600601
fieldData.forEach(nextRecord => {
@@ -620,19 +621,24 @@ class RelayQueryWriter extends RelayQueryVisitor<WriterState> {
620621

621622
const path = RelayQueryPath.getPath(state.path, field, nextLinkedID);
622623
this.createRecordIfMissing(field, nextLinkedID, path, nextRecord);
624+
nextRecords[nextLinkedID] = {record: nextRecord, path};
623625
isUpdate = isUpdate || nextLinkedID !== prevLinkedID;
624-
625-
this.traverse(field, {
626-
nodeID: null, // never propagate `nodeID` past the first linked field
627-
path,
628-
recordID: nextLinkedID,
629-
responseData: nextRecord,
630-
});
631626
nextIndex++;
632627
});
633-
628+
// Write the linked records before traverse to prevent generating extraneous
629+
// client ids.
634630
this._writer.putLinkedRecordIDs(recordID, storageKey, nextLinkedIDs);
635-
631+
nextLinkedIDs.forEach(nextLinkedID => {
632+
const itemData = nextRecords[nextLinkedID];
633+
if (itemData) {
634+
this.traverse(field, {
635+
nodeID: null, // never propagate `nodeID` past the first linked field
636+
path: itemData.path,
637+
recordID: nextLinkedID,
638+
responseData: itemData.record,
639+
});
640+
}
641+
});
636642
// Only broadcast a list-level change if a record was changed/added/removed
637643
if (
638644
isUpdate ||

src/traversal/__tests__/writeRelayQueryPayload_pluralLinkedField-test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,5 +428,47 @@ describe('writeRelayQueryPayload()', () => {
428428
writePayload(store, writer, query, payload);
429429
expect(store.getType('123')).toBe('User');
430430
});
431+
432+
it('does not overwrite nested child field', () => {
433+
const records = {};
434+
const store = new RelayRecordStore({records});
435+
const writer = new RelayRecordWriter(records, {}, false);
436+
const query = getNode(Relay.QL`
437+
query {
438+
node(id: "1") {
439+
... on Story {
440+
attachments {
441+
target {
442+
attachments {
443+
styleList
444+
}
445+
}
446+
}
447+
}
448+
}
449+
}
450+
`);
451+
const styleList = ['Image'];
452+
const payload = {
453+
node: {
454+
id: '1',
455+
attachments: [{
456+
target: {
457+
id: '1',
458+
attachments: [{
459+
styleList,
460+
}],
461+
},
462+
}],
463+
__typename: 'Story',
464+
},
465+
};
466+
writePayload(store, writer, query, payload);
467+
const attachmentIDs = store.getLinkedRecordIDs('1', 'attachments');
468+
expect(attachmentIDs.length).toBe(1);
469+
expect(store.getField(attachmentIDs[0], 'styleList'))
470+
.toEqual(styleList);
471+
expect(store.getLinkedRecordID(attachmentIDs[0], 'target')).toBe('1');
472+
});
431473
});
432474
});

0 commit comments

Comments
 (0)