Last Updated: 4/6/2026
Fetching Data in Components
This guide explains how to fetch GeoJSON and JSON data files in Vue components for the “Where Did They Go?” application. The project uses custom composable functions that provide reactive data loading with automatic retry logic and loading states.
The Fetch Composables
The application provides two composable functions in client/src/utility/fetchers.js:
fetchGeojson(pathString)— Fetches and parses GeoJSON filesfetchJson(pathString)— Fetches and parses JSON files
Both functions return the same result object structure:
{
result: {
data, // ref: parsed data or null
loading, // ref: true while fetching, false when complete
error // ref: error object if fetch fails, otherwise null
},
promise, // Promise from the initial fetch
refresh // function: re-fetch the data
}Basic Usage in a Component
Here’s how to fetch GeoJSON data when a component mounts:
import { onMounted, watch } from 'vue';
import { fetchGeojson } from '../utility/fetchers';
onMounted(() => {
const { result } = fetchGeojson('/kansas/geojson/railroads.geojson');
renderToSVG(result);
});
function renderToSVG(r) {
let d = r.data.value;
let l = r.loading.value;
let e = r.error.value;
if (l) {
// Data is still loading - watch for completion
const unwatch = watch(
() => r.loading.value,
() => {
renderToSVG(r);
unwatch();
}
);
return;
} else if (e) {
// Handle error
console.error(e);
return;
}
// Use the loaded data
// d.features contains the GeoJSON features array
}Automatic Retry Logic
Both fetch composables include built-in retry logic. If a fetch fails, the function automatically retries up to 3 times (configurable via the maxRetries parameter in the internal fetchWrapper function). Only after all retries fail will the error ref be populated.
This retry mechanism helps handle transient network issues without requiring manual error recovery code in every component.
Using FetchQueue for Sequential Loading
For components that need to fetch data in a specific order or manage multiple concurrent fetches, use the FetchQueue class from client/src/utility/FetchQueue.js:
import { FetchQueue } from '../utility/FetchQueue';
const queue = new FetchQueue();
// Enqueue multiple fetches
const { result, promise } = fetchGeojson('/kansas/geojson/KSCounty_1860_GeoJSON.geojson');
queue.enqueue(promise, result, renderToSVG);The FetchQueue enforces first-in-first-out (FIFO) resolution order. Each callback receives the result object once the previous promise resolves. The queue automatically resets after 50 enqueued promises (configurable via the constructor’s max parameter).
Data File Locations
The Express backend serves static files from server/public/ via the express.static() middleware configured in server/app.js. All data files accessible to the frontend are located within this directory:
- GeoJSON files:
server/public/kansas/geojson/— County borders, cities, railroads, water features, healthcare facilities, schools - JSON data files:
server/public/kansas/json/— Population data and other tabular datasets
Note: The server/data/ directory exists in the repository but is NOT served by Express and is not accessible via HTTP requests from the frontend.
All paths in fetchGeojson() and fetchJson() are relative to the server root (server/public/).
Example: Fetching County Borders
The BorderData.vue component demonstrates fetching GeoJSON with a queue:
import { fetchGeojson } from '../utility/fetchers';
import { FetchQueue } from '../utility/FetchQueue';
const queue = new FetchQueue();
onMounted(() => {
let { result, promise } = fetchGeojson(
'/kansas/geojson/KSCounty_1860_GeoJSON.geojson'
);
queue.enqueue(promise, result, renderToSVG);
});
// Later, when the year changes:
hooks.onYearChange((newValue) => {
let { result, promise } = fetchGeojson(
`/kansas/geojson/KSCounty_${newValue}_GeoJSON.geojson`
);
queue.enqueue(promise, result, renderToSVG);
});Rendering GeoJSON to SVG
Once data loads, use D3’s geoPath generator to convert GeoJSON features into SVG path elements:
import * as d3 from 'd3';
const pathGen = d3.geoPath(props.properties.projection);
function renderToSVG(r) {
let d = r.data.value;
// ... check loading and error states ...
selection = gTag
.selectAll('.rail')
.data(d.features)
.join(
(enter) =>
enter
.append('path')
.attr('d', pathGen)
.classed('rail', true),
(update) => update,
(exit) => exit.remove()
);
}The pathGen function expects GeoJSON Feature objects and returns SVG path data strings.
What’s Next
- D3 Style Guide – Learn the project’s D3 coding standards
- Data Sources – Reference for all data files and their structures
- Basemap Hook System – See how the main map component orchestrates data layers