I am using React Places Autocomplete to generate location suggestions. I want to force user to select one of the suggested locations, so I am trying to detect the clicks outside the elements generated here:
我正在使用React Places Autocomplete来生成位置建议。我想强制用户选择一个建议的位置,所以我试图检测在这里生成的元素之外的点击:
<div ref={suggestionsContainerRef}>
{suggestions.map(suggestion => {
const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div {...getSuggestionItemProps(suggestion, { className, style })} >
<span >{suggestion.description}</span>
</div>
)
})}
</div>
This is not working as expected. Even I click on one of the span elements generated, it considers the click outside of the div. Any help?
这并没有像预期的那样奏效。即使我单击生成的SPAN元素之一,它也会认为是在div之外的单击。有什么帮助吗?
Full Code:
完整代码:
type LocationInputProps = {
id: string
label: string
placeholder: string
}
const LocationInput = ({id, label, placeholder}: LocationInputProps) => {
const [address, setAddress] = useState<string>('');
const [lat, setLat] = useState<number>();
const [lon, setLon] = useState<number>();
const [selectedAddress, setSelectedAddress] = useState(false);
const suggestionsContainerRef = useRef<HTMLDivElement | null>(null);
useEffect(() => {
// Add a click event listener to the document to detect clicks outside the suggestions container
document.addEventListener('click', handleDocumentClick);
return () => {
// Remove the click event listener when the component unmounts
document.removeEventListener('click', handleDocumentClick);
};
}, []);
const handleDocumentClick = (event: MouseEvent) => {
// Check if the click target is not within the suggestions container
if (
suggestionsContainerRef.current &&
!suggestionsContainerRef.current.contains(event.target as Node)
) {
console.log('click is not within container')
setAddress(''); // Clear the input value
}
};
return(
<PlacesAutocomplete
value={address}
onChange={(address) => {setAddress(address)}}
onSelect={(address) => {
geocodeByAddress(address)
.then(results => getLatLng(results[0]))
.then(latLng => {console.log('Success', latLng)
setLat(latLng.lat);
setLon(latLng.lng);
setSelectedAddress(true);
})
.catch(error => {console.error('Error', error)
setSelectedAddress(false)});
setAddress(address);
}}
searchOptions={{componentRestrictions: {country: 'US'}}}
>
{({ getInputProps, suggestions, getSuggestionItemProps }) => (
<div>
<div className="grid w-9/12 items-center gap-1.5">
<Label>{label}</Label>
<Input id={id} placeholder={placeholder} {...getInputProps({
className: 'location-search-input'
})}/>
</div>
<div ref={suggestionsContainerRef}>
{suggestions.map(suggestion => {
const className = suggestion.active ? 'suggestion-item--active' : 'suggestion-item';
// inline style for demonstration purpose
const style = suggestion.active
? { backgroundColor: '#fafafa', cursor: 'pointer' }
: { backgroundColor: '#ffffff', cursor: 'pointer' };
return (
<div {...getSuggestionItemProps(suggestion, { className, style })} >
<span >{suggestion.description}</span>
</div>
)
})}
</div>
</div>
)}
</PlacesAutocomplete>
)
}
export default LocationInput
更多回答
Could you try and give the ref to to the div
that encloses the span
你能试着把引用给包围跨度的div吗?
yup already tried that, it is not working either
是的,我已经试过了,它也不起作用
I have created a minimally reproducible example and at first glance it works as expected. Could you please check it and tell me if I missed something. codesandbox.io/s/hungry-meninsky-f66mw4?file=/src/App.js You could also try to log actual container and childNodes and look at their DOM to make sure they are correct.
我已经创建了一个可重复性最低的示例,乍一看,它的工作情况与预期一致。你能帮我查一下吗?如果我遗漏了什么,请告诉我。Codesandbox.io/s/hungry-meninsky-f66mw4?file=/src/App.js您还可以尝试记录实际的容器和子节点,并查看它们的DOM以确保它们是正确的。
@DmitriyZhiganov thanks for the demo, your demo works when we have fixed number of suggesstions but the google places api dynamically changes the suggestions hence the suggestion div changes in every keystroke that is why it doesn't work
@Dmitriyzhiganov感谢您的演示,当我们有固定数量的建议时,您的演示可以工作,但Google Places API会动态更改建议,因此建议div在每次击键时都会更改,这就是它不起作用的原因
我是一名优秀的程序员,十分优秀!