メインコンテンツまでスキップ

Add Custom Search data to Search Box (React)

This example demonstrates how to pass custom data into the <SearchBox> React component so that search results include both custom search results and Mapbox provided results. To do this, you must leverage the componentOptions.customSearch which is available to the @mapbox/search-js-react wrapper.

The example below contains an array of formatted features data called airports which represent small airfields in the Northeast United States. This data can come from any source like an external API or local data, but it must be formatted as a suggestion result as returned by the Search Box API. Also, each suggestion needs to contain a _geometry object that includes coordinates and type properties as specified in the retrieved Feature format. This allows our custom data to work interchangeably when it is returned inside SearchBox.

The customSearch parameter receives the search query from SearchBox and we pass this to the async searchAirports() function that returns a Promise which resolves to our custom search data suggestions.

Search for '44N', 'Sky Acres' or 'IZG' to see the custom airport data being returned within the Search Box results. If your application included a map, you could then click on a custom data result and handle that on the map as you'd like.

import { useRef, useEffect, useState } from 'react';
import { SearchBox } from '@mapbox/search-js-react';
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';


// TO MAKE THE MAP APPEAR YOU MUST
// ADD YOUR ACCESS TOKEN FROM
// https://account.mapbox.com
const ACCESS_TOKEN = 'YOUR_MAPBOX_ACCESS_TOKEN'

const MapboxExample = () => {

const mapRef = useRef();
const mapContainerRef = useRef();
const [mapLoaded, setMapLoaded] = useState(false);
const center = [-70.25463, 43.66097] // starting position [lng, lat] of Portland, ME

const airports = [
// This data has been formatted to match the format specified in the customSearch documentation
// http://docs.mapbox.com/mapbox-search-js/api/web/search/#mapboxsearchboxcomponentoptions-properties-customsearch
{
"name": "4AK7 - Aleknagik Mission Strip",
"place_formatted": "ALEKNAGIK, AK",
"mapbox_id": "airport_4AK7",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-158.597221680699,
59.2809237361098
]
}
},
{
"name": "44N - Sky Acres",
"place_formatted": "MILLBROOK, NY",
"mapbox_id": "airport_44N",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-73.7380239239491,
41.7074323474509
]
}
},
{
"name": "3B1 - Greenville Muni",
"place_formatted": "GREENVILLE, ME",
"mapbox_id": "airport_3B1",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-69.5516497188597,
45.4628406764533
]
}
},
{
"name": "IZG - Eastern Slopes Rgnl",
"place_formatted": "FRYEBURG, ME",
"mapbox_id": "airport_IZG",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-70.9478895415445,
43.9911478692315
]
}
},
{
"name": "BHB - Hancock County/Bar Harbor",
"place_formatted": "BAR HARBOR, ME",
"mapbox_id": "airport_BHB",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-68.3614895334381,
44.4497144207149
]
}
},
{
"name": "EEN - Dillant/Hopkins",
"place_formatted": "KEENE, NH",
"mapbox_id": "airport_EEN",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-72.2707787994177,
42.8983976236563
]
}
},
{
"name": "PVC - Provincetown Muni",
"place_formatted": "PROVINCETOWN, MA",
"mapbox_id": "airport_PVC",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-70.2207225212066,
42.0722864225276
]
}
},
{
"name": "4B0 - South Albany",
"place_formatted": "SOUTH BETHLEHEM, NY",
"mapbox_id": "airport_4B0",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-73.8339459545136,
42.5607308383581
]
}
},
{
"name": "1C3 - Argyle",
"place_formatted": "ARGYLE, NY",
"mapbox_id": "airport_1C3",
"feature_type": "airport",
"_geometry": {
"type": "Point",
"coordinates": [
-73.4701958825037,
43.2545365362011
]
}
}
]

const searchAirports = async(query) => {
// We lowerCase() both the query and the airport name to ensure consistent matching
const q = query.toLowerCase().trim()
const matches = airports.filter(a => a.name.toLowerCase().includes(q))
return matches
}

useEffect(() => {

mapboxgl.accessToken = ACCESS_TOKEN;

mapRef.current = new mapboxgl.Map({
container: mapContainerRef.current,
center: center,
zoom: 7 // starting zoom
});

mapRef.current.on('load', () => {
setMapLoaded(true);
});

},[])

return (
<div style={{height: '100%', width: '100%', position: 'relative'}} ref={mapContainerRef}>
<div
style={{
margin: 20,
position: 'absolute',
top: 0,
right: 0,
zIndex: 20,
width: 300
}}>

<SearchBox
accessToken={ACCESS_TOKEN}
map={mapLoaded ? mapRef.current : undefined}
proximity={center}
mapboxgl={mapboxgl}
marker
componentOptions={{
customSearch: (value) => searchAirports(value)
}}/>
</div>
</div>

)
}

export default MapboxExample;
このexampleは役に立ちましたか?