2458
id: number,
2459
path: Array<string | number>,
2460
): void {
2461
- const isCurrent = isMostRecentlyInspectedElementCurrent(id);
2462
- if (isCurrent) {
2461
+ if (isMostRecentlyInspectedElement(id)) {
2462
window.$attribute = getInObject(
2463
((mostRecentlyInspectedElement: any): InspectedElement),
2464
path,
2765
2766
let mostRecentlyInspectedElement: InspectedElement | null = null;
2767
let hasElementUpdatedSinceLastInspected: boolean = false;
2768
+ let currentlyInspectedPaths: Object = {};
2769
2770
- function isMostRecentlyInspectedElementCurrent(id: number): boolean {
2770
+ function isMostRecentlyInspectedElement(id: number): boolean {
2771
return (
2772
mostRecentlyInspectedElement !== null &&
2773
- mostRecentlyInspectedElement.id === id &&
2774
- !hasElementUpdatedSinceLastInspected
2773
+ mostRecentlyInspectedElement.id === id
2774
);
2775
}
2776
2777
+ function isMostRecentlyInspectedElementCurrent(id: number): boolean {
2778
+ return (
2779
+ isMostRecentlyInspectedElement(id) && !hasElementUpdatedSinceLastInspected
2780
+ );
2781
+ }
2782
+
2783
+ // Track the intersection of currently inspected paths,
2784
+ // so that we can send their data along if the element is re-rendered.
2785
+ function mergeInspectedPaths(path: Array<string | number>) {
2786
+ let current = currentlyInspectedPaths;
2787
+ path.forEach(key => {
2788
+ if (!current[key]) {
2789
+ current[key] = {};
2790
+ }
2791
+ current = current[key];
2792
+ });
2793
+ }
2794
+
2795
function createIsPathAllowed(
2796
key: string | null,
2797
secondaryCategory: 'hooks' | null,
2781
- inspectedPaths: Object,
2798
) {
2799
// This function helps prevent previously-inspected paths from being dehydrated in updates.
2800
// This is important to avoid a bad user experience where expanded toggles collapse on update.
2819
break;
2820
}
2821
2806
- let current = key === null ? inspectedPaths : inspectedPaths[key];
2822
+ let current =
2823
+ key === null ? currentlyInspectedPaths : currentlyInspectedPaths[key];
2824
if (!current) {
2825
return false;
2826
}
2887
path: Array<string | number>,
2888
count: number,
2889
): void {
2873
- const isCurrent = isMostRecentlyInspectedElementCurrent(id);
2874
-
2875
- if (isCurrent) {
2890
+ if (isMostRecentlyInspectedElement(id)) {
2891
const value = getInObject(
2892
((mostRecentlyInspectedElement: any): InspectedElement),
2893
path,
2902
}
2903
2904
function copyElementPath(id: number, path: Array<string | number>): void {
2890
- const isCurrent = isMostRecentlyInspectedElementCurrent(id);
2891
-
2892
- if (isCurrent) {
2905
+ if (isMostRecentlyInspectedElement(id)) {
2906
copyToClipboard(
2907
getInObject(
2908
((mostRecentlyInspectedElement: any): InspectedElement),
2915
function inspectElement(
2916
requestID: number,
2917
id: number,
2905
- inspectedPaths: Object,
2906
- forceUpdate: boolean,
2918
+ path: Array<string | number> | null,
2919
): InspectedElementPayload {
2908
- const isCurrent = !forceUpdate && isMostRecentlyInspectedElementCurrent(id);
2920
+ if (path !== null) {
2921
+ mergeInspectedPaths(path);
2922
+ }
2923
2910
- if (isCurrent) {
2911
- // If this element has not been updated since it was last inspected, we don't need to return it.
2912
- // Instead we can just return the ID to indicate that it has not changed.
2913
- return {
2914
- id,
2915
- responseID: requestID,
2916
- type: 'no-change',
2917
- };
2924
+ if (isMostRecentlyInspectedElement(id)) {
2925
+ if (!hasElementUpdatedSinceLastInspected) {
2926
+ if (path !== null) {
2927
+ let secondaryCategory = null;
2928
+ if (path[0] === 'hooks') {
2929
+ secondaryCategory = 'hooks';
2930
+ }
2931
+
2932
+ // If this element has not been updated since it was last inspected,
2933
+ // we can just return the subset of data in the newly-inspected path.
2934
+ return {
2935
+ id,
2936
+ responseID: requestID,
2937
+ type: 'hydrated-path',
2938
+ path,
2939
+ value: cleanForBridge(
2940
+ getInObject(
2941
+ ((mostRecentlyInspectedElement: any): InspectedElement),
2942
+ path,
2943
+ ),
2944
+ createIsPathAllowed(null, secondaryCategory),
2945
+ path,
2946
+ ),
2947
+ };
2948
+ } else {
2949
+ // If this element has not been updated since it was last inspected, we don't need to return it.
2950
+ // Instead we can just return the ID to indicate that it has not changed.
2951
+ return {
2952
+ id,
2953
+ responseID: requestID,
2954
+ type: 'no-change',
2955
+ };
2956
+ }
2957
+ }
2958
+ } else {
2959
+ currentlyInspectedPaths = {};
2960
}
2961
2962
hasElementUpdatedSinceLastInspected = false;
2981
const cleanedInspectedElement = {...mostRecentlyInspectedElement};
2982
cleanedInspectedElement.context = cleanForBridge(
2983
cleanedInspectedElement.context,
2942
- createIsPathAllowed('context', null, inspectedPaths),
2984
+ createIsPathAllowed('context', null),
2985
);
2986
cleanedInspectedElement.hooks = cleanForBridge(
2987
cleanedInspectedElement.hooks,
2946
- createIsPathAllowed('hooks', 'hooks', inspectedPaths),
2988
+ createIsPathAllowed('hooks', 'hooks'),
2989
);
2990
cleanedInspectedElement.props = cleanForBridge(
2991
cleanedInspectedElement.props,
2950
- createIsPathAllowed('props', null, inspectedPaths),
2992
+ createIsPathAllowed('props', null),
2993
);
2994
cleanedInspectedElement.state = cleanForBridge(
2995
cleanedInspectedElement.state,
2954
- createIsPathAllowed('state', null, inspectedPaths),
2996
+ createIsPathAllowed('state', null),
2997
);
2998
2999
return {