Skip to content

Commit

Permalink
✨ Use useQuery hook to reduce verbosity
Browse files Browse the repository at this point in the history
  • Loading branch information
homersimpsons committed Nov 21, 2024
1 parent 1969796 commit e4398af
Showing 1 changed file with 18 additions and 58 deletions.
76 changes: 18 additions & 58 deletions src/components/OSMElementData/OSMElementData.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,15 @@ import SvgSymbol from '../SvgSymbol/SvgSymbol'
import BusySpinner from '../BusySpinner/BusySpinner'
import messages from './Messages'
import './OSMElementData.scss'
import { useQuery } from 'react-query'

const OSM_SERVER = window.env.REACT_APP_OSM_SERVER

const OSMElementData = props => {
const [selectedFeatureId, setSelectedFeatureId] = useState(null)
const [element, setElement] = useState(null)
const [fetchingElement, setFetchingElement] = useState(null)
const [fetchedElement, setFetchedElement] = useState(null)
const [failedElement, setFailedElement] = useState(null)
const [fetchErr, setFetchErr] = useState(null)

const { fetchOSMElement, taskBundle, task: primaryTask } = props

const featureIds = useMemo(() => {
const allTasks = taskBundle ? taskBundle.tasks : [primaryTask]
const allTasks = taskBundle ? taskBundle.tasks : [primaryTask]
return _flatten(_compact(_map(allTasks, task => {
const geometries = AsMappableTask(task).normalizedGeometries()
return geometries ? _compact(_map(
Expand All @@ -38,64 +32,27 @@ const OSMElementData = props => {
})))
}, [primaryTask, taskBundle])

// If there is no selected feature or it is no longer available (e.g. because a task bundle
// was unbundled), then update the selection
useEffect(() => {
if (!selectedFeatureId || featureIds.indexOf(selectedFeatureId) === -1) {
setSelectedFeatureId(featureIds[0] ?? null)
}
}, [featureIds, selectedFeatureId])

// Fetch and process the OSM Data
useEffect(() => {
if (selectedFeatureId === null) {
// No features to fetch, cleanup existing to ensure consistency
setElement(null)
setFetchedElement(null)
return
}

// If we're already fetching data for the active feature, or if the fetch failed, or if we already have its data,
// there's nothing to do
if (fetchingElement === selectedFeatureId || failedElement === selectedFeatureId || fetchedElement === selectedFeatureId) {
return
}
const [selectedFeatureId, setSelectedFeatureId] = useState(featureIds[0] ?? null)

setFetchingElement(selectedFeatureId)
setFailedElement(null)
setFetchErr(null)
fetchOSMElement(selectedFeatureId).then(element => {
// If for some reason we don't get any element entries, record a failure
// to prevent further attempts to refetch
if (!element) { // TODO Can this happen ?
setFailedElement(selectedFeatureId)
setFetchingElement(null)
return
}

setFetchedElement(selectedFeatureId)
setElement(element)
setFetchingElement(null)
}).catch(err => {
setFailedElement(selectedFeatureId)
setFetchErr(err)
setFetchingElement(null)
})
}, [selectedFeatureId, fetchingElement, failedElement, fetchedElement, fetchOSMElement])
const { isPending, isError, error: fetchErr, data: element } = useQuery({
queryKey: ['OSMElement', selectedFeatureId],
queryFn: () => selectedFeatureId
? fetchOSMElement(selectedFeatureId)
: null
})

if (fetchingElement) {
if (isPending) {
return (
<div className="mr-flex mr-justify-center mr-items-center mr-w-full mr-h-full">
<BusySpinner />
</div>
)
}

const activeFeatureId = selectedFeatureId ? selectedFeatureId : featureIds[0]
if (failedElement === activeFeatureId) {
if (isError) {
return (
<div className="mr-flex mr-flex-col mr-text-red-light">
<FormattedMessage {...messages.elementFetchFailed} values={{element: activeFeatureId}} />
<FormattedMessage {...messages.elementFetchFailed} values={{element: selectedFeatureId}} />
{fetchErr && fetchErr.defaultMessage && <FormattedMessage {...fetchErr} />}
</div>
)
Expand All @@ -107,19 +64,22 @@ const OSMElementData = props => {
)
}

const tagsValues = _map(element.tag, tag => <Fragment key={tag.k}><dt>{tag.k}</dt><dd>{tag.v}</dd></Fragment>)
const tagsValues = _map(
element.tag,
({k, v}) => <Fragment key={k}><dt>{k}</dt><dd>{v}</dd></Fragment>
)

return (
<div className="mr-mr-4">
<div className="mr-flex mr-justify-between mr-links-green-lighter mr-mb-4">
<FeatureSelectionDropdown
featureIds={featureIds}
selectedFeatureId={activeFeatureId}
selectedFeatureId={selectedFeatureId}
selectFeatureId={setSelectedFeatureId}
/>
<a
className="mr-button mr-button--xsmall"
href={`${OSM_SERVER}/${activeFeatureId}`}
href={`${OSM_SERVER}/${selectedFeatureId}`}
target="_blank"
rel="noopener noreferrer"
>
Expand Down

0 comments on commit e4398af

Please sign in to comment.