У меня есть пользовательский компонент LocationSearch
, который является просто оболочкой для местоположения Google Автозаполнение .Иногда адрес длиннее поля ввода, поэтому я применил Reactstrap Tooltip , который показывает полный адрес.Проблема в том, что если у меня есть два из этих компонентов на одной странице, и я наведу курсор мыши на одно из полей ввода, обе подсказки будут запущены, так как на странице также есть еще один компонент LocationSearch
.Как я могу только запустить всплывающую подсказку, над которой я нахожу, и не запустить все остальные?
Мой LocationSearch
компонент выглядит так:
export default class LocationSearch extends Component {
constructor(props) {
super(props);
this.state = {
addressSearch: this.props.value || '',
address: {},
tooltipKey: false
};
this.toggleTooltip = this.toggleTooltip.bind(this);
}
toggleTooltip() {
let tooltipOpen = !this.state.tooltipOpen;
if (!this.state.addressSearch) {
tooltipOpen = false;
}
this.setState({
tooltipOpen
});
}
handleAddressSearch = (addressSearch) => {
this.setState({
addressSearch,
});
};
handleSelect = (addressSearch) => {
let scope = this;
geocodeByAddress(addressSearch)
.then(results => {
let street_number, route, city, state, zip, country = "";
if (results.length > 0) {
let result = results[0];
for (let i = 0; i < result.address_components.length; i++) {
let component = result.address_components[i];
for (let x = 0; x < component.types.length; x++) {
let type = component.types[x];
switch (type) {
case "street_number":
street_number = component.long_name || '';
break;
case "route":
route = component.long_name || '';
break;
case "locality":
city = component.long_name;
break;
case "administrative_area_level_1":
state = component.short_name;
break;
case "postal_code":
zip = component.long_name;
break;
case "country":
country = component.long_name;
break;
}
}
}
let address = scope.state.address;
if (street_number && route) {
address.address1 = street_number + ' ' + route;
} else {
address.address1 = '';
}
address.city = city;
address.state = state;
address.zip = zip;
address.country = country;
address.googlePlacesId = result.place_id;
scope.setState({
addressSearch: FormatAddress(address) // just formats a string version of the address object to display in the text box
});
getLatLng(results[0]).then(function (latLon) {
let date = new Date();
let url = `https://maps.googleapis.com/maps/api/timezone/json?location=${latLon.lat},${latLon.lng}×tamp=${date.getTime() / 1000}&key=${GOOGLE_API_CONFIG.mapsKey}`;
axios.get(url)
.then(function (response) {
address.timezone = response.data.timeZoneId;
scope.props.handleSelect(address);
})
.catch(function (error) {
console.error("Timezone lookup error:", error);
address.timezone = 'US/Arizona';
scope.props.handleSelect(address);
});
})
}
})
.catch(error => {
console.error('Error', error);
})
};
handleCloseClick = () => {
this.setState({
addressSearch: '',
address: {},
tooltipOpen: false
});
};
handleError = (status, clearSuggestions) => {
console.error('Error from Google Maps API', status); // eslint-disable-line no-console
this.setState({errorMessage: status}, () => {
clearSuggestions();
});
};
render() {
if (this.props.hidden) {
return null;
}
return (
<FormGroup>
{this.props.label !== '' && (
<Label for="address">{this.props.label}</Label>
)}
<PlacesAutocomplete
onChange={this.handleAddressSearch}
value={this.state.addressSearch}
onSelect={this.handleSelect}
onError={this.props.handleError || this.handleError}
shouldFetchSuggestions={!!(this.state.addressSearch && this.state.addressSearch.length > 2)}
>
{({getInputProps, suggestions, getSuggestionItemProps}) => {
return (
<div className="search-bar-container">
<div className="search-input-container" href="#" id="addressTooltip">
<input
{...getInputProps({
placeholder: this.props.placeholder,
className: "search-input"
})}
disabled={this.props.disabled}
/>
{this.state.addressSearch && this.state.addressSearch.length > 0 && !this.props.disabled && (
<button
className="clear-button"
onClick={this.handleCloseClick}
>
x
</button>
)}
</div>
<Tooltip placement="top" isOpen={this.state.tooltipOpen} target="addressTooltip" toggle={this.toggleTooltip}>
{this.state.addressSearch ? this.state.addressSearch : ''}
</Tooltip>
{suggestions.length > 0 && (
<div className="autocomplete-container">
{suggestions.map(suggestion => {
const className = classNames('suggestion-item', {
'suggestion-item--active': suggestion.active,
});
return (
/* eslint-disable react/jsx-key */
<div
{...getSuggestionItemProps(suggestion, {className})}
>
<strong>
{suggestion.formattedSuggestion.mainText}
</strong>{' '}
<small>
{suggestion.formattedSuggestion.secondaryText}
</small>
</div>
);
/* eslint-enable react/jsx-key */
})}
<div className="dropdown-footer">
<div>
<img
src={require('../../assets/img/powered_by_google_default.png')}
className="dropdown-footer-image"
/>
</div>
</div>
</div>
)}
</div>
);
}}
</PlacesAutocomplete>
</FormGroup>
)
}
}
И форма, которая реализует два LocationSearch
компоненты, выглядит примерно так:
import LocationSearch from "../../../../components/locationsearch/LocationSearch";
export default class Addresses extends React.Component {
constructor(props) {
super(props);
this.state = {
address1: {},
address1Str: '',
address2: {},
address2Str: '',
}
}
handleAddress1Select = (address1) => {
this.setState({
address1,
address1Str: FormatAddress(address1)
})
};
handleAddress2Select = (address2) => {
this.setState({
address2,
address2Str: FormatAddress(address2)
})
};
render() {
return (
<div>
<LocationSearch
label='Address 1'
placeholder='Street address...'
handleSelect={this.handleAddress1Select}
value={this.state.address1Str}
/>
<LocationSearch
label='Address 2'
placeholder='Street address...'
handleSelect={this.handleAddress2Select}
value={this.state.address2Str}
/>
</div>
)
}
}
Вот скриншот всплывающей подсказки над одним из полей адреса.Как видно из другого поля ввода адреса внизу, отображается undefined
, и всплывающие подсказки запускаются при наведении курсора на верхнюю.
Есть ли какой-нибудь способ иметь настраиваемое поле всплывающей подсказки в состоянии LocationSearch
для каждого экземпляра компонента?