Select parent node if selection is removed
Dan Abramov committed
Apr 24, 2019 at 16:29 UTC
949384f4ca20651e56d1180289868d774162707e
2 files changed
+25
-16
src/devtools/store.js
+6
-7
@@ -540,7 +540,7 @@ export default class Store extends EventEmitter {
540
// The Tree context's search reducer expects an explicit list of ids for nodes that were added or removed.
541
// In this case, we can pass it empty arrays since nodes in a collapsed tree are still there (just hidden).
542
// Updating the selected search index later may require auto-expanding a collapsed subtree though.
543
- this.emit('mutated', [[], []]);
543
+ this.emit('mutated', [[], new Map()]);
544
}
545
}
546
}
@@ -625,7 +625,9 @@ export default class Store extends EventEmitter {
625
}
626
627
const addedElementIDs: Array<number> = [];
628
- const removedElementIDs: Array<number> = [];
628
+ // This is a mapping of removed ID -> parent ID:
629
+ const removedElementIDs: Map<number, number> = new Map();
630
+ // We'll use the parent ID to adjust selection if it gets deleted.
631
632
let i = 2;
633
while (i < operations.length) {
@@ -789,7 +791,7 @@ export default class Store extends EventEmitter {
791
}
792
793
this._adjustParentTreeWeight(parentElement, -element.weight);
792
- removedElementIDs.push(id);
794
+ removedElementIDs.set(id, parentID);
795
}
796
break;
797
}
@@ -871,10 +873,7 @@ export default class Store extends EventEmitter {
873
console.groupEnd();
874
}
875
874
- this.emit('mutated', [
875
- new Uint32Array(addedElementIDs),
876
- new Uint32Array(removedElementIDs),
877
- ]);
876
+ this.emit('mutated', [addedElementIDs, removedElementIDs]);
877
};
878
879
onProfilingStatus = (isProfiling: boolean) => {
src/devtools/views/Components/TreeContext.js
+19
-9
@@ -67,7 +67,7 @@ type ACTION_GO_TO_PREVIOUS_SEARCH_RESULT = {|
67
|};
68
type ACTION_HANDLE_STORE_MUTATION = {|
69
type: 'HANDLE_STORE_MUTATION',
70
- payload: [Uint32Array, Uint32Array],
70
+ payload: [Array<number>, Map<number, number>],
71
|};
72
type ACTION_RESET_OWNER_STACK = {|
73
type: 'RESET_OWNER_STACK',
@@ -169,10 +169,20 @@ function reduceTreeState(store: Store, state: State, action: Action): State {
169
numElements = store.numElements;
170
171
// If the currently-selected Element has been removed from the tree, update selection state.
172
- if (
172
+ const removedIDs = action.payload[1];
173
+ // Find the closest parent that wasn't removed during this batch.
174
+ // We deduce the parent-child mapping from removedIDs (id -> parentID)
175
+ // because by now it's too late to read them from the store.
176
+ while (
177
selectedElementID !== null &&
174
- store.getElementByID(selectedElementID) === null
178
+ removedIDs.has(selectedElementID)
179
) {
180
+ selectedElementID = ((removedIDs.get(
181
+ selectedElementID
182
+ ): any): number);
183
+ }
184
+ if (selectedElementID === 0) {
185
+ // The whole root was removed.
186
selectedElementIndex = null;
187
}
188
break;
@@ -312,7 +322,7 @@ function reduceSearchState(store: Store, state: State, action: Action): State {
322
removedElementIDs,
323
] = (action: ACTION_HANDLE_STORE_MUTATION).payload;
324
315
- removedElementIDs.forEach(id => {
325
+ removedElementIDs.forEach((parentID, id) => {
326
// Prune this item from the search results.
327
const index = searchResults.indexOf(id);
328
if (index >= 0) {
@@ -738,10 +748,10 @@ function TreeContextController({ children }: Props) {
748
749
// Mutations to the underlying tree may impact this context (e.g. search results, selection state).
750
useEffect(() => {
741
- const handleStoreMutated = ([
742
- addedElementIDs,
743
- removedElementIDs,
744
- ]: Array<Uint32Array>) => {
751
+ const handleStoreMutated = ([addedElementIDs, removedElementIDs]: [
752
+ Array<number>,
753
+ Map<number, number>,
754
+ ]) => {
755
dispatchWrapper({
756
type: 'HANDLE_STORE_MUTATION',
757
payload: [addedElementIDs, removedElementIDs],
@@ -755,7 +765,7 @@ function TreeContextController({ children }: Props) {
765
// It would only impact the search state, which is unlikely to exist yet at this point.
766
dispatchWrapper({
767
type: 'HANDLE_STORE_MUTATION',
758
- payload: [new Uint32Array(0), new Uint32Array(0)],
768
+ payload: [[], new Map()],
769
});
770
}
771