Fixed hydration for events meta data
This commit is contained in:
parent
cf19916be7
commit
a2c79f2d9e
|
@ -2149,25 +2149,37 @@ export function attach(
|
|||
});
|
||||
}
|
||||
|
||||
function createIsPathWhitelisted(isHooksPath: boolean, key: string | null) {
|
||||
function createIsPathWhitelisted(
|
||||
key: string | null,
|
||||
secondaryCategory: 'events' | 'hooks' | null
|
||||
) {
|
||||
// This function helps prevent previously-inspected paths from being dehydrated in updates.
|
||||
// This is important to avoid a bad user experience where expanded toggles collapse on update.
|
||||
return function isPathWhitelisted(path: Array<string | number>): boolean {
|
||||
// Dehydrating the 'subHooks' property makes the HooksTree UI a lot more complicated,
|
||||
// so it's easiest for now if we just don't break on this boundary.
|
||||
// We can always dehydrate a level deeper (in the value object).
|
||||
if (isHooksPath) {
|
||||
if (path.length === 1) {
|
||||
// Never dehydrate the hooks object at the top level.
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
path[path.length - 1] === 'subHooks' ||
|
||||
path[path.length - 2] === 'subHooks'
|
||||
) {
|
||||
// Never dehydrate the subHooks array
|
||||
return true;
|
||||
}
|
||||
switch (secondaryCategory) {
|
||||
case 'events':
|
||||
if (path.length <= 2) {
|
||||
// Never dehydrate the "hooks" object at the top level (becaues it's always just an array).
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 'hooks':
|
||||
if (path.length === 1) {
|
||||
// Never dehydrate the "hooks" object at the top levels.
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
path[path.length - 1] === 'subHooks' ||
|
||||
path[path.length - 2] === 'subHooks'
|
||||
) {
|
||||
// Dehydrating the 'subHooks' property makes the HooksTree UI a lot more complicated,
|
||||
// so it's easiest for now if we just don't break on this boundary.
|
||||
// We can always dehydrate a level deeper (in the value object).
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
let current =
|
||||
|
@ -2195,6 +2207,13 @@ export function attach(
|
|||
if (path != null) {
|
||||
mergeInspectedPaths(path);
|
||||
|
||||
let secondaryCategory = null;
|
||||
if (path[0] === 'events') {
|
||||
secondaryCategory = 'events';
|
||||
} else if (path[0] === 'hooks') {
|
||||
secondaryCategory = 'hooks';
|
||||
}
|
||||
|
||||
// If this element has not been updated since it was last inspected,
|
||||
// we can just return the subset of data in the newly-inspected path.
|
||||
return {
|
||||
|
@ -2206,7 +2225,7 @@ export function attach(
|
|||
((mostRecentlyInspectedElement: any): InspectedElement),
|
||||
path
|
||||
),
|
||||
createIsPathWhitelisted(path[0] === 'hooks', null),
|
||||
createIsPathWhitelisted(null, secondaryCategory),
|
||||
path
|
||||
),
|
||||
};
|
||||
|
@ -2246,23 +2265,23 @@ export function attach(
|
|||
const cleanedInspectedElement = { ...mostRecentlyInspectedElement };
|
||||
cleanedInspectedElement.context = cleanForBridge(
|
||||
cleanedInspectedElement.context,
|
||||
createIsPathWhitelisted(false, 'context')
|
||||
createIsPathWhitelisted('context', null)
|
||||
);
|
||||
cleanedInspectedElement.events = cleanForBridge(
|
||||
cleanedInspectedElement.events,
|
||||
createIsPathWhitelisted(false, 'events')
|
||||
createIsPathWhitelisted('events', 'events')
|
||||
);
|
||||
cleanedInspectedElement.hooks = cleanForBridge(
|
||||
cleanedInspectedElement.hooks,
|
||||
createIsPathWhitelisted(true, 'hooks')
|
||||
createIsPathWhitelisted('hooks', 'hooks')
|
||||
);
|
||||
cleanedInspectedElement.props = cleanForBridge(
|
||||
cleanedInspectedElement.props,
|
||||
createIsPathWhitelisted(false, 'props')
|
||||
createIsPathWhitelisted('props', null)
|
||||
);
|
||||
cleanedInspectedElement.state = cleanForBridge(
|
||||
cleanedInspectedElement.state,
|
||||
createIsPathWhitelisted(false, 'state')
|
||||
createIsPathWhitelisted('state', null)
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
display: flex;
|
||||
}
|
||||
|
||||
.Name {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.Empty {
|
||||
color: var(--color-dimmer);
|
||||
font-style: italic;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import { copy } from 'clipboard-js';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import styles from './EventsTree.css';
|
||||
|
@ -7,15 +9,32 @@ import KeyValue from './KeyValue';
|
|||
import ExpandCollapseToggle from './ExpandCollapseToggle';
|
||||
import { serializeDataForCopy } from '../utils';
|
||||
|
||||
type Props = {|
|
||||
import type { GetInspectedElementPath } from './InspectedElementContext';
|
||||
|
||||
type InspectPath = (path: Array<string | number>) => void;
|
||||
|
||||
type EventsTreeViewProps = {|
|
||||
events: Object,
|
||||
getInspectedElementPath: GetInspectedElementPath,
|
||||
id: number,
|
||||
|};
|
||||
|
||||
function EventsTreeView({ events }: Props) {
|
||||
function EventsTreeView({
|
||||
events,
|
||||
getInspectedElementPath,
|
||||
id,
|
||||
}: EventsTreeViewProps) {
|
||||
const handleCopy = useCallback(() => copy(serializeDataForCopy(events)), [
|
||||
events,
|
||||
]);
|
||||
|
||||
const inspectPath = useCallback(
|
||||
(path: Array<string | number>) => {
|
||||
getInspectedElementPath(id, ['events', ...path]);
|
||||
},
|
||||
[getInspectedElementPath, id]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={styles.EventsTree}>
|
||||
<div className={styles.HeaderRow}>
|
||||
|
@ -26,16 +45,26 @@ function EventsTreeView({ events }: Props) {
|
|||
</Button>
|
||||
}
|
||||
</div>
|
||||
<InnerEventsTreeView events={events} />
|
||||
<InnerEventsTreeView events={events} inspectPath={inspectPath} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function InnerEventsTreeView({ events }: Props) {
|
||||
type InnerEventsTreeViewProps = {|
|
||||
events: Object,
|
||||
inspectPath: InspectPath,
|
||||
|};
|
||||
|
||||
function InnerEventsTreeView({
|
||||
events,
|
||||
inspectPath,
|
||||
}: InnerEventsTreeViewProps) {
|
||||
return events.map((event, index) => (
|
||||
<EventComponentView
|
||||
key={index}
|
||||
displayName={event.displayName}
|
||||
index={index}
|
||||
inspectPath={inspectPath}
|
||||
props={event.props}
|
||||
/>
|
||||
));
|
||||
|
@ -43,11 +72,19 @@ function InnerEventsTreeView({ events }: Props) {
|
|||
|
||||
type EventComponentViewProps = {|
|
||||
displayName: string,
|
||||
index: number,
|
||||
inspectPath: InspectPath,
|
||||
props: null | Object,
|
||||
|};
|
||||
|
||||
function EventComponentView({ displayName, props }: EventComponentViewProps) {
|
||||
function EventComponentView({
|
||||
displayName,
|
||||
index,
|
||||
inspectPath,
|
||||
props,
|
||||
}: EventComponentViewProps) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
let eventComponentProps = null;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let children;
|
||||
|
@ -74,8 +111,9 @@ function EventComponentView({ displayName, props }: EventComponentViewProps) {
|
|||
<KeyValue
|
||||
key={name}
|
||||
depth={1}
|
||||
inspectPath={inspectPath}
|
||||
name={name}
|
||||
path={[name]}
|
||||
path={[index]}
|
||||
value={(eventComponentProps: any)[name]}
|
||||
/>
|
||||
))}
|
||||
|
|
|
@ -336,7 +336,13 @@ function InspectedElementView({
|
|||
inspectPath={inspectContextPath}
|
||||
overrideValueFn={overrideContextFn}
|
||||
/>
|
||||
{events !== null && events.length > 0 && <EventsTree events={events} />}
|
||||
{events !== null && events.length > 0 && (
|
||||
<EventsTree
|
||||
events={events}
|
||||
getInspectedElementPath={getInspectedElementPath}
|
||||
id={id}
|
||||
/>
|
||||
)}
|
||||
|
||||
{ownerID === null && owners !== null && owners.length > 0 && (
|
||||
<div className={styles.Owners}>
|
||||
|
|
Loading…
Reference in New Issue