【问题标题】:React - How to restrict Google Places API results to specific countries dynamicallyReact - 如何动态地将 Google Places API 结果限制在特定国家/地区
【发布时间】:2020-11-08 01:56:36
【问题描述】:

我正在尝试将自动完成结果动态限制在某个国家/地区。现在我可以初始化 API 脚本并获取默认国家/地区的 reslts,但是一旦用户更改国家/地区,我正在运行以下脚本,但它什么也没做:

setAutocompleteCountry = () => {
    if (this.state.country == 'all') {
      autoComplete.setComponentRestrictions({'country': []});
    } else {
      autoComplete.setComponentRestrictions({'country': country});
    }
}

感谢任何见解,这里是组件中的相关代码:


let autoComplete;
let country = 'vn'

class ServiceableAreas extends Component {
    constructor(props) {
        super(props)
        this.state = {
            query: '',
            country: 'th'
        }
        this.autoCompleteRef = React.createRef(null);
    }

    componentDidUpdate(prevProps, prevState) {
        const { city } = this.props.values;
        if (city !== prevProps.values.city) {
            if (city !== null) {

                if (city === 'Bangkok') {
                    country = 'th'
                }
                else if (city === 'Vientiane') {
                    country = 'la'
                }
                else if (city === 'Hoh Chi Min') {
                    country = 'vn'
                }
                this.setAutocompleteCountry()
            }
        }
    }

    componentDidMount() {
        this.loadScript(
            "https://maps.googleapis.com/maps/api/js?key=AIzaSyD4FpFjf7nQ0LDaz3qi1EShX2p4Yy0rnxo&libraries=places",
            () => this.handleScriptLoad(this.setQuery, this.autoCompleteRef)
          );
    }

    setQuery = (query) => {
        this.setState({query})
    }
    
    // dynamically load JavaScript files in our html with callback when finished
    loadScript = (url, callback) => {
        let script = document.createElement("script"); // create script tag
        script.type = "text/javascript";
    
        // when script state is ready and loaded or complete we will call callback
        if (script.readyState) {
        script.onreadystatechange = function() {
            if (script.readyState === "loaded" || script.readyState === "complete") {
            script.onreadystatechange = null;
            callback();
            }
        };
        } else {
            script.onload = () => callback();
        }
    
        script.src = url; // load by url
        document.getElementsByTagName("head")[0].appendChild(script); // append to head
    };

    // handle when the script is loaded we will assign autoCompleteRef with google maps place autocomplete
    handleScriptLoad = (updateQuery, autoCompleteRef) => {
        // assign autoComplete with Google maps place one time
        autoComplete = new window.google.maps.places.Autocomplete(
        autoCompleteRef.current,
        { types: ["(regions)"], componentRestrictions: { country: country } }
        );
        // autoComplete.setFields(["address_components", "formatted_address"]); // specify what properties we will get from API
        autoComplete.setFields(["address_components"]); // specify what properties we will get from API
        // add a listener to handle when the place is selected
        autoComplete.addListener("place_changed", () =>
            this.handlePlaceSelect(updateQuery)
        );
    }

    // Set the country restriction based on user input.
    setAutocompleteCountry = () => {
        if (this.state.country == 'all') {
          autoComplete.setComponentRestrictions({'country': []});
        } else {
          autoComplete.setComponentRestrictions({'country': country});
        }
    }

    handlePlaceSelect = async (updateQuery) => {
        const addressObject = await autoComplete.getPlace(); // get place from google api
        const query = addressObject.formatted_address;
        updateQuery(query);
        console.log(addressObject);
        const _area = addressObject.address_components.filter(item => item.types.filter(t => t === 'sublocality_level_1').length > 0)[0]
        //console.log('_AREA: ', _area)
        if (_area !== undefined) {
            const area = _area.long_name;
            console.log('AREA: ', area)
            if (this.props.values.serviceableAreas.indexOf(area) === -1) {
                const areas = [...this.props.values.serviceableAreas, area]
                this.props.setServiceableAreas(areas)
                this.setState({query: ''})
            }
            else {
                this.setState({query: ''})
                this.focus()
            }
        }
        else {
            this.setState({query: ''})
            this.focus()
        }
      }
 
    render() {
        const { values } = this.props;
  
              <div>
                <Grid container spacing={1}>
                    <Grid item md={12}>
                        <TextField
                            inputRef={this.autoCompleteRef}
                            label='Area'
                            placeholder="Enter area"
                            onChange={event => this.setQuery(event.target.value)}
                            value={this.state.query}
                            InputProps={{ disableUnderline: true }}
                            fullWidth
                        />
                    </Grid>
                </Grid>        
            </div>
        )
    }
}
            
export default ServiceableAreas

【问题讨论】:

  • 什么都没做 - 你期望会发生什么?你怎么知道它什么也没做?
  • @MrUpsidown 我的意思是它没有达到我的预期,也就是说,当我更改国家/地区时,它并没有改变谷歌自动完成国家/地区限制
  • 你如何测试它? autoComplete.setComponentRestrictions({'country':'th'});应该将国家限制设置为泰国。
  • 非常感谢您的反馈!

标签: reactjs google-places-api


【解决方案1】:

这是一个非常基本的示例,演示了setComponentRestrictions() 的用法。输入一封信,您将在法国看到建议。将选项更改为 USA 并在自动完成字段中单击返回,您将看到来自 USA 的建议。

function initialize() {

  var ac = new google.maps.places.Autocomplete(
    (document.getElementById('autocomplete')), {
      types: ['geocode'],
      componentRestrictions: {
        country: 'fr'
      }
    });

  google.maps.event.addDomListener(document.getElementById('country'), 'change', function() {

    ac.setComponentRestrictions({
      'country': this.value
    });
  });
}
#autocomplete {
  width: 300px;
}
<input id="autocomplete" placeholder="Enter your address" type="text">
<select id="country">
  <option value="fr">France</option>
  <option value="us">USA</option>
</select>

<!-- Replace the value of the key parameter with your own API key. -->
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=places&callback=initialize" async defer></script>

【讨论】:

    猜你喜欢
    • 2016-06-22
    • 2017-08-05
    • 1970-01-01
    • 2017-08-28
    • 2016-04-02
    • 2016-01-25
    • 2015-09-03
    • 2012-07-23
    • 1970-01-01
    相关资源
    最近更新 更多