@loadsmart/react-location-select
v5.0.0
Published
Location Select component, based on Miranda's Select, for React applications.
Downloads
1,120
Maintainers
Keywords
Readme
LocationSelect
This project belongs to Loadsmart's front-end team.
This is a spin-off of Miranda [React] Select
powered with Google Autocomplete, Places, and Geocoder capabilities.
Getting started
To install it, run:
npm i @loadsmart/react-location-select
or
yarn add @loadsmart/react-location-select
Please, make sure that you also have all the peer dependencies listed in the package.json installed.
How to use
Important:
- You need to provide the
googleMapsAPIKey
prop for theSelect
to be visible and ready for location selection. - If you add a custom datasource, make sure its reference is stable (i.e., you won't generate a new reference
unnecessarily) so the
Select
can appropriately optimize its data source management. - If you add a custom
config
for the Google Maps datasource, make sure its reference is stable (i.e., you won't generate a new reference unnecessarily) so theSelect
can appropriately optimize its data source management.
import LocationSelect from '@loadsmart/react-location-select';
<LocationSelect {...props} googleMapsAPIKey={'<Your Google Maps API key>'} />;
The Google Maps datasource will always be included. You can customize how it fetches locations, if needed, by
providing the config
prop. This is the default config
:
const DEFAULT_CONFIG = {
// Source: https://developers.google.com/maps/documentation/places/web-service/supported_types#table3
types: 'cities',
// Source: https://developers.google.com/maps/documentation/javascript/reference/places-autocomplete-service#ComponentRestrictions
restrictions: { country: ['us', 'ca'] },
// Source: https://developers.google.com/maps/documentation/javascript/reference/3.45/places-service#PlaceResult
fields: ['address_components', 'place_id'],
};
Mocking the returned locations
You most certainly will need unit tests around the code that will use the LocationSelect
component. We export a mock factory to help returning the locations you want to work on your tests.
import {
GoogleMapsMock,
GoogleMapsMockFactory,
} from '@loadsmart/react-location-select/dist/testing';
// Save the original google reference to reset it after the test is completed
const originalWindowGoogle = window.google;
// Generate mock data using a default info.
// e.g. { "address": "New York, NY, United States" }
window.google = GoogleMapsMock();
// Or generate mock data with an overridden info.
window.google = GoogleMapsMockFactory({
predictionStub(query) {
return new Promise((resolve) => {
resolve({
predictions: [
{
description: 'New York, NY, United States',
id: '7eae6a016a9c6f58e2044573fb8f14227b6e1f96',
matched_substrings: [
{
length: 2,
offset: 0,
},
],
place_id: 'ChIJOwg_06VPwokRYv534QaPC8g',
reference: '...',
structured_formatting: {
main_text: 'New York, NY, United States',
main_text_matched_substrings: [
{
length: 2,
offset: 0,
},
],
secondary_text: '',
},
terms: [
{
offset: 0,
value: 'New York',
},
{
offset: 10,
value: 'NY',
},
{
offset: 14,
value: 'United States',
},
],
types: ['locality', 'political', 'geocode'],
},
],
});
});
},
geocodeStub(query, callback) {
if (query.address === '' || query.placeId === '') {
callback([], 'ZERO_RESULTS');
return;
}
callback(
[
{
address_components: [
{
long_name: 'New York',
short_name: 'New York',
types: ['locality', 'political'],
},
{
long_name: 'New York',
short_name: 'NY',
types: ['administrative_area_level_1', 'political'],
},
{
long_name: 'United States',
short_name: 'US',
types: ['country', 'political'],
},
],
formatted_address: 'New York, NY, USA',
geometry: {
bounds: {
south: 40.4773991,
west: -74.25908989999999,
north: 40.9175771,
east: -73.70027209999999,
},
location: { lat: 40.7127753, lng: -74.0059728 },
location_type: 'APPROXIMATE',
viewport: {
south: 40.4773991,
west: -74.25908989999999,
north: 40.9175771,
east: -73.70027209999999,
},
},
place_id: 'ChIJOwg_06VPwokRYv534QaPC8g',
types: ['locality', 'political'],
},
],
'OK',
);
},
placesStub(query, callback) {
callback(
{
address_components: [
{
long_name: 'Newark',
short_name: 'Newark',
types: ['locality', 'political'],
},
{
long_name: 'Essex County',
short_name: 'Essex County',
types: ['administrative_area_level_2', 'political'],
},
{
long_name: 'New Jersey',
short_name: 'NJ',
types: ['administrative_area_level_1', 'political'],
},
{
long_name: 'United States',
short_name: 'US',
types: ['country', 'political'],
},
],
place_id: 'ChIJHQ6aMnBTwokRc-T-3CrcvOE',
geometry: {
location: {
lat: () => 0,
lng: () => 0,
},
},
html_attributions: [],
},
'OK',
);
},
});
// Reset the mock after the test is completed.
afterAll(() => {
window.google = originalWindowGoogle;
});
Using a custom parser
You can pass one or more custom parsers and manipulate the returned data if you need a different result than the default LocationSelect
config.
const customParser = (query, location) => {
return location;
};
<LocationSelect {...args} config={{ parsers: [customParser] }} />;
Using a custom adapter
If you need a different adapter to display the select options, you can pass a custom adapter and change the data that is returned.
const customAdapter = {
getKey(location) {
return location?.address;
},
getLabel(location) {
return location?.address;
},
};
<LocationSelect {...args} config={{ adapter: customAdapter }} />;
Using on a TypeScript project
You can import the types from this package.
import { LocationSelect } from '@loadsmart/react-location-select';
import type {
Location,
LocationParser,
// ... Any other type
} from '@loadsmart/react-location-select';
The @types/google.maps is installed by this package, don't worry about it. You can use it without importing or installing anything.
Contribute
First, make sure you have your env set to Node >= 16.
To successfully run this project on your local environment and obtain data from Compass, please adhere to the following steps:
- Change the component stories by adding the
compassConfig.APIKey
insrc/location-select/location-select.stories.tsx
.- You can learn how to get a key here
export const Demo: Story = {
args: {
name: 'location',
googleMapsAPIKey: '<YOUR GOOGLE MAPS API KEY GOES HERE>',
multiple: true,
disableMapsLoading: false,
googleMapsAPIVersion: '3.51',
+ compassConfig: {
+ baseURL: 'https://api.staging.loadsmart.com',
+ APIKey: '<API_KEY>',
+ },
},
render: DemoRenderer,
};
The
dev
command runs on port 8080, which has the necessary permissions to establish requests to Compass in stating.