Skip to content

Commit 578cae2

Browse files
refactors
1 parent 7603239 commit 578cae2

File tree

11 files changed

+310
-218
lines changed

11 files changed

+310
-218
lines changed

examples/playground/src/components/JsonView.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ interface Props {
55
onClick?: () => void
66
}
77

8+
/**
9+
* Renders any object as JSON on a scrollable pane
10+
*/
811
export default function JsonView({ content, onClick }: Props) {
912
return (
1013
<div className={clsx("pane overflow-auto w-full no-scrollbar", onClick && "cursor-pointer")}>
Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,31 @@
1-
import { AmdbLayerName, getAmdbAPI } from "@navigraph/amdb"
2-
import { useQueries } from "@tanstack/react-query"
1+
import { AmdbLayerName } from "@navigraph/amdb"
32
import { circleMarker, geoJson, GeoJSON } from "leaflet"
43
import { memo, useEffect, useRef } from "react"
54
import { renderToString } from "react-dom/server"
65
import { useMap } from "react-leaflet"
76
import { useRecoilValue } from "recoil"
7+
import useAmdbLayers from "../../hooks/useAmdbLayers"
88
import { amdbLayersState } from "../../state/amdb"
99
import JsonView from "../JsonView"
1010
import amdbStyle, { layerOrder } from "./amdbStyle"
1111

12-
const AmdbManager = memo(() => {
13-
const amdb = getAmdbAPI()
14-
12+
/**
13+
* Handles the rendering of AMDB layers to the map for a specific airport
14+
*/
15+
function AmdbLayer({ idarpt, layerNames }: { idarpt: string; layerNames: AmdbLayerName[] }) {
1516
const map = useMap()
1617

17-
const amdbLayers = useRecoilValue(amdbLayersState)
18-
19-
const data = useQueries({
20-
queries: amdbLayers.flatMap(([idarpt, layers]) =>
21-
layers.map(layer => ({
22-
queryKey: ["amdb-data", idarpt, layer],
23-
queryFn: async () => ({ idarpt, layer, data: await amdb.getAmdbLayer({ icao: idarpt, layer }) }),
24-
})),
25-
),
26-
})
18+
const data = useAmdbLayers(idarpt, layerNames)
2719

28-
const layers = useRef<{ idarpt: string; layerName: AmdbLayerName; layer: GeoJSON }[]>([])
20+
// Store references to the layer instances
21+
const layers = useRef<{ layerName: AmdbLayerName; layer: GeoJSON }[]>([])
2922

23+
// This use effect will run each time the layer data or layers to render has (probably) updated
3024
useEffect(() => {
31-
const toRemove = layers.current.filter(
32-
({ idarpt, layerName }) => !data.some(({ data }) => data?.idarpt === idarpt && data?.layer === layerName),
33-
)
25+
// Find layers which are no longer present in the queried data
26+
const toRemove = layers.current.filter(({ layerName }) => !data.some(([_layerName]) => _layerName === layerName))
3427

28+
// Remove these layers from the map and from the stored references
3529
toRemove.forEach(({ layer }) => {
3630
map.removeLayer(layer)
3731
layers.current.splice(
@@ -40,20 +34,17 @@ const AmdbManager = memo(() => {
4034
)
4135
})
4236

43-
const newLayers = data.flatMap(({ data }) => {
44-
if (
45-
data?.data &&
46-
!layers.current.some(({ idarpt, layerName }) => idarpt === data.idarpt && layerName === data.layer)
47-
) {
37+
// Create layers which there is now queried data for, but no stored layer for it
38+
const newLayers = data.flatMap(([layerName, data]) => {
39+
if (data && !layers.current.some(x => x.layerName === layerName)) {
4840
return [
4941
{
50-
idarpt: data.idarpt,
51-
layerName: data.layer,
52-
layer: geoJson(data.data, {
53-
style: amdbStyle(data.layer),
42+
layerName,
43+
layer: geoJson(data, {
44+
style: amdbStyle,
5445

5546
pointToLayer: (feature, latlng) => {
56-
const marker = circleMarker(latlng, amdbStyle(data.layer)(feature))
47+
const marker = circleMarker(latlng, amdbStyle(feature))
5748

5849
marker.feature = feature
5950

@@ -67,7 +58,7 @@ const AmdbManager = memo(() => {
6758
const feature = target.feature
6859

6960
if (feature?.type === "Feature") {
70-
const style = amdbStyle(data.layer)(feature)
61+
const style = amdbStyle(feature)
7162

7263
style.stroke = true
7364
style.color = "blue"
@@ -84,8 +75,8 @@ const AmdbManager = memo(() => {
8475
_layer.bindPopup(
8576
renderToString(
8677
<div className="flex flex-col items-center gap-2">
87-
<span className="text-ng-background-200">{data.layer}</span>
88-
<JsonView content={feature.properties} />
78+
<span className="text-ng-background-200">{layerName}</span>
79+
<JsonView content={feature.properties as unknown} />
8980
</div>,
9081
),
9182
)
@@ -99,17 +90,28 @@ const AmdbManager = memo(() => {
9990
return []
10091
})
10192

102-
newLayers.forEach(({ idarpt, layerName, layer }) => {
93+
// Add the new layers to the map and store the references
94+
newLayers.forEach(({ layerName, layer }) => {
10395
map.addLayer(layer)
104-
layers.current.push({ idarpt, layerName, layer })
96+
layers.current.push({ layerName, layer })
10597
})
10698

99+
// Sort the layers and bring them to front in that correct order to ensure they appear in the correct order on the map
107100
layers.current
108101
.sort((a, b) => layerOrder[b.layerName] - layerOrder[a.layerName])
109102
.forEach(({ layer }) => layer.bringToFront())
110103
}, [data, map])
111104

112105
return null
106+
}
107+
108+
/**
109+
* Handles the rendering of selected AMDB layers from selected airports to the leaflet map
110+
*/
111+
const AmdbManager = memo(() => {
112+
const amdbLayers = useRecoilValue(amdbLayersState)
113+
114+
return amdbLayers.map(([idarpt, layerNames]) => <AmdbLayer idarpt={idarpt} layerNames={layerNames} />)
113115
})
114116

115117
export default AmdbManager

0 commit comments

Comments
 (0)