11import "./GraphInspector.css" ;
22import type { SyntheticEvent } from "react" ;
3- import { useCallback , useEffect , useReducer , useRef , useState } from "react" ;
3+ import { useCallback , useEffect , useReducer , useState , useRef } from "react" ;
44import TreeView from "@mui/lab/TreeView" ;
5- import { Node } from "./Node" ;
65import { allQuery , node } from "./queries" ;
76import { graphReducer } from "./graphReducer" ;
87import { VertexNode } from "../../../../graphql/types" ;
98import { MinusSquare , PlusSquare } from "./icons" ;
109import { StyledTreeItem } from "./StyledTreeItem" ;
1110import { fetchGraphQL } from "../../graphql/fetchGraphql" ;
12- import { Loader } from "../Loader/Loader" ;
13- import { useQuery } from 'urql' ;
14- import type { Page } from '../../../../graphql/relay' ;
11+ import { useQuery } from "urql" ;
12+ import type { Page } from "../../../../graphql/relay" ;
13+ import { DynamicRowVirtualizer } from "./DynamicRowVirtualizer" ;
14+
1515const emptyGraph = { graph : { } } ;
1616
1717const limit = 5 ;
1818
1919export function GraphInspector ( ) : JSX . Element {
20- // TODO: call setAfter when scrolling
21- const [ after ] = useState ( '' ) ;
20+ const [ after , setAfter ] = useState ( "" ) ;
2221 const [ typename , setTypename ] = useState < string | undefined > ( ) ;
22+ // TODO: this really needs to go at some point and the rangeExtractor prop of
23+ // useVirtualized seems a better way to go
24+ // https://tanstack.com/virtual/v3/docs/api/virtualizer#rangeextractor
25+ // measureElement might be useful here too
26+ // https://tanstack.com/virtual/v3/docs/api/virtualizer#measureelement
27+ const [ update , forceUpdate ] = useReducer ( ( x ) => x + 1 , 0 ) ;
2328
2429 const [ result ] = useQuery < { all : Page < VertexNode > } , {
2530 typename : string ;
2631 first : number ;
2732 after : string ;
2833 } > ( {
2934 query : allQuery ,
30- pause : ! typename ,
35+ pause : ! typename && ! after ,
3136 variables : {
3237 typename,
3338 first : limit ,
34- after
39+ after,
3540 } ,
3641 } ) ;
3742
3843 const [ { graph } , dispatch ] = useReducer ( graphReducer , emptyGraph ) ;
3944 const expandedNodes = useRef ( new Set < string > ( ) ) ;
4045
41- const { data, error } = result ;
46+ const { data, error, fetching } = result ;
4247
4348 useEffect ( ( ) => {
4449 const edges = data ?. all ?. edges ?? [ ] ;
@@ -51,10 +56,10 @@ export function GraphInspector(): JSX.Element {
5156 type : "ALL" ,
5257 payload : {
5358 typename,
54- nodes : edges . map ( edge => edge . node ) ,
59+ nodes : edges . map ( ( edge ) => edge . node ) ,
5560 } ,
5661 } ) ;
57- } , [ data , typename ] )
62+ } , [ data , typename ] ) ;
5863
5964 const handleChange = useCallback (
6065 async ( _ : SyntheticEvent , nodeIds : string [ ] ) => {
@@ -115,11 +120,17 @@ export function GraphInspector(): JSX.Element {
115120 }
116121 }
117122
123+ setTimeout ( forceUpdate , 300 ) ;
124+
118125 return ;
119126 }
120127
128+ setAfter ( "" ) ;
121129 setTypename ( nodeId ) ;
122- } , [ ] ,
130+
131+ setTimeout ( forceUpdate , 300 ) ;
132+ } ,
133+ [ ] ,
123134 ) ;
124135
125136 useEffect ( ( ) => {
@@ -146,40 +157,39 @@ export function GraphInspector(): JSX.Element {
146157 }
147158
148159 if ( error ) {
149- return < p className = "error" > Oh no... { error ?. message } </ p >
160+ return < p className = "error" > Oh no... { error ?. message } </ p > ;
150161 }
151162
152163 return (
153- < TreeView
154- aria-label = "graph inspector"
155- defaultCollapseIcon = { < MinusSquare /> }
156- defaultExpandIcon = { < PlusSquare /> }
157- onNodeToggle = { handleChange }
158- multiSelect = { false }
159- >
160- { Object . values ( graph ) . map ( ( { typename, label, nodes } ) => (
161- < StyledTreeItem
162- key = { typename }
163- nodeId = { typename }
164- label = { < div className = "root" > { label } </ div > }
165- >
166- { nodes . length > 0
167- ? nodes . map ( ( vertexNode , i ) => (
168- < StyledTreeItem
169- key = { vertexNode . id }
170- nodeId = { vertexNode . id }
171- label = {
172- < Node
173- parentId = { `${ typename } .nodes.${ i } ` }
174- node = { vertexNode }
175- />
176- }
177- />
178- )
179- )
180- : < Loader /> }
181- </ StyledTreeItem >
182- ) ) }
183- </ TreeView >
164+ < div >
165+ < TreeView
166+ aria-label = "graph inspector"
167+ defaultCollapseIcon = { < MinusSquare /> }
168+ defaultExpandIcon = { < PlusSquare /> }
169+ onNodeToggle = { handleChange }
170+ multiSelect = { false }
171+ >
172+ { Object . values ( graph ) . map ( ( { typename, label, nodes } ) => (
173+ < StyledTreeItem
174+ key = { typename }
175+ nodeId = { typename }
176+ label = { < div className = "root" > { label } </ div > }
177+ >
178+ { nodes . length > 0
179+ ? (
180+ < DynamicRowVirtualizer
181+ hasNextPage = { ! ! data ?. all ?. pageInfo ?. hasNextPage }
182+ nodes = { nodes }
183+ typename = { typename }
184+ fetching = { fetching }
185+ fetchNextPage = { ( ) => setAfter ( data . all . pageInfo . endCursor ) }
186+ update = { update }
187+ />
188+ )
189+ : < div > loading....</ div > }
190+ </ StyledTreeItem >
191+ ) ) }
192+ </ TreeView >
193+ </ div >
184194 ) ;
185195}
0 commit comments