1- import { useEffect , useMemo , useRef , useState } from 'react' ;
1+ import { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
22import { StyleSheet , View } from 'react-native' ;
33import ChartManager from './ChartManager' ;
44import { Grid } from '@mui/material' ;
5- import ChartItem from './ChartItem' ;
5+ import ChartItem , { Coordinate } from './ChartItem' ;
66import Arrow from './Arrow' ;
77
8- type Coordinate = {
9- x : number ;
10- y : number ;
11- } ;
12-
138type FlowChartProps = {
149 chartManager : ChartManager ;
1510} ;
1611
17- const getCenter = ( side : number , size : number ) => side + size / 2 ;
18-
1912export default function FlowChart ( { chartManager } : FlowChartProps ) {
20- const itemsRef = useRef < View [ ] > ( [ ] ) ;
13+ const coordinates = useMemo < Map < number , Coordinate > > ( ( ) => new Map ( ) , [ ] ) ;
14+
2115 const rootRef = useRef < View > ( null ) ;
2216
17+ const updateCoordinates = useCallback (
18+ ( id : number , coordinate : Coordinate ) => {
19+ const htmlRootElement = rootRef . current as unknown as HTMLElement ;
20+ const root = htmlRootElement . getBoundingClientRect ( ) ;
21+
22+ // Adjust to root relative positioning
23+ coordinates . set ( id , {
24+ x : coordinate . x - root . left ,
25+ y : coordinate . y - root . top ,
26+ } ) ;
27+ } ,
28+ [ coordinates ]
29+ ) ;
30+
2331 // Arrows are not shown on the first render on production builds.
2432 // This `counter` forces a re-render after the component is mounted.
2533 const [ counter , setCounter ] = useState ( 0 ) ;
@@ -30,31 +38,6 @@ export default function FlowChart({ chartManager }: FlowChartProps) {
3038 return ( ) => clearTimeout ( timeout ) ;
3139 } , [ counter ] ) ;
3240
33- const itemsCoords = useMemo < Coordinate [ ] > (
34- ( ) =>
35- itemsRef . current . map ( ( element : View | undefined ) => {
36- // During unloading or reresizing, element may reload itself, causing it to be undefined
37- if ( ! element ) {
38- return {
39- x : 0 ,
40- y : 0 ,
41- } as Coordinate ;
42- }
43-
44- const htmlElement = element as unknown as HTMLElement ;
45- const htmlRootElement = rootRef . current as unknown as HTMLElement ;
46-
47- const box = htmlElement . getBoundingClientRect ( ) ;
48- const root = htmlRootElement . getBoundingClientRect ( ) ;
49-
50- return {
51- x : getCenter ( box . left , box . width ) - root . left ,
52- y : getCenter ( box . top , box . height ) - root . top ,
53- } as Coordinate ;
54- } ) ,
55- [ ]
56- ) ;
57-
5841 return (
5942 < View style = { styles . container } ref = { rootRef } >
6043 < Grid container rowGap = { 4 } >
@@ -65,9 +48,7 @@ export default function FlowChart({ chartManager }: FlowChartProps) {
6548 . map ( ( item ) => (
6649 < ChartItem
6750 key = { item . id }
68- innerRef = { ( el ) => {
69- itemsRef . current [ item . id ] = el ;
70- } }
51+ updateCoordinates = { updateCoordinates }
7152 item = { item }
7253 chartManager = { chartManager }
7354 />
@@ -78,19 +59,23 @@ export default function FlowChart({ chartManager }: FlowChartProps) {
7859 { chartManager . connections . map ( ( connection ) => {
7960 // we have all the connections layed out,
8061 // but the user may choose not to use some of the available items,
81- if ( ! itemsCoords [ connection . from ] || ! itemsCoords [ connection . to ] ) {
62+ if (
63+ ! coordinates . get ( connection . from ) ||
64+ ! coordinates . get ( connection . to )
65+ ) {
8266 return < View key = { connection . id } /> ;
8367 }
68+
8469 return (
8570 < Arrow
8671 key = { connection . id }
8772 startPoint = { {
88- x : itemsCoords [ connection . from ] . x ,
89- y : itemsCoords [ connection . from ] . y ,
73+ x : coordinates . get ( connection . from ) . x ,
74+ y : coordinates . get ( connection . from ) . y ,
9075 } }
9176 endPoint = { {
92- x : itemsCoords [ connection . to ] . x ,
93- y : itemsCoords [ connection . to ] . y ,
77+ x : coordinates . get ( connection . to ) . x ,
78+ y : coordinates . get ( connection . to ) . y ,
9479 } }
9580 />
9681 ) ;
0 commit comments