diff --git a/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx b/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx index 39f4c7721..872bfaa93 100644 --- a/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx +++ b/desktop/flipper-plugin/src/ui/data-inspector/DataInspector.tsx @@ -82,6 +82,7 @@ type DataInspectorState = { filterExpanded: DataInspectorExpanded; userExpanded: DataInspectorExpanded; filter: string; + hoveredNodePath: string | undefined; }; const MAX_RESULTS = 50; @@ -102,6 +103,7 @@ export class DataInspector extends PureComponent< userExpanded: {}, filterExpanded: {}, filter: '', + hoveredNodePath: undefined, }; static getDerivedStateFromProps( @@ -181,6 +183,16 @@ export class DataInspector extends PureComponent< }); }; + setHoveredNodePath = (path?: string) => { + this.setState({ + hoveredNodePath: path, + }); + }; + + removeHover = () => { + this.setHoveredNodePath(undefined); + }; + // make sure this fn is a stable ref to not invalidate the whole tree on new data getRootData = () => { return this.props.data; @@ -188,10 +200,12 @@ export class DataInspector extends PureComponent< render() { return ( - + ReactElement[]; - onMouseEnter?: () => void; + hoveredNodePath?: string; - onMouseExit?: () => void; + setHoveredNodePath: (path: string) => void; }; const defaultValueExtractor: DataValueExtractor = (value: any) => { @@ -315,14 +315,13 @@ export const DataInspectorNode: React.FC = memo( tooltips, setValue: setValueProp, additionalContextMenuItems, - onMouseEnter, - onMouseExit, + hoveredNodePath, + setHoveredNodePath, }) { const highlighter = useHighlighter(); const getRoot = useContext(RootDataContext); const isUnitTest = useInUnitTest(); - const [hover, setHover] = useState(false); const shouldExpand = useRef(false); const expandHandle = useRef(undefined as any); const [renderExpanded, setRenderExpanded] = useState(false); @@ -428,37 +427,6 @@ export const DataInspectorNode: React.FC = memo( [onDelete], ); - const thisOnMouseEnter = useCallback( - (e: SyntheticEvent) => { - onMouseEnter?.(); - e.stopPropagation(); - setHover(true); - }, - [onMouseEnter], - ); - - const thisOnMouseLeave = useCallback( - (e: SyntheticEvent) => { - onMouseExit?.(); - e.stopPropagation(); - setHover(false); - }, - [onMouseExit], - ); - - const childOnMouseEnter = useCallback(() => { - //when a child is hovered we are in both child and parents bounds so - //manually disable our own hover state so we focus on child - setHover(false); - }, []); - - const childOnMouseExit = useCallback(() => { - //If a child has been unhovered then it means we have left the childs bounds and mouse should still be in parents - //(current element's) bounds. However the mouse enter callback wont fire again in this element since we never left the bounds. - //Therefore we manually set hovered back to true - setHover(true); - }, []); - /** * RENDERING */ @@ -502,8 +470,8 @@ export const DataInspectorNode: React.FC = memo( const metaKey = key + index; const dataInspectorNode = ( = memo( ); } + const nodePath = path.join('.'); + return ( { + setHoveredNodePath(nodePath); + }} + onMouseLeave={() => { + setHoveredNodePath(parentPath.join('.')); + }} depth={depth} disabled={!!setValueProp && !!setValue === false}> @@ -755,7 +729,8 @@ function dataInspectorPropsAreEqual( nextProps.onDelete === props.onDelete && nextProps.setValue === props.setValue && nextProps.collapsed === props.collapsed && - nextProps.expandRoot === props.expandRoot + nextProps.expandRoot === props.expandRoot && + nextProps.hoveredNodePath === props.hoveredNodePath ); }