Resolving React Warning: Maximum Update Depth Exceeded in Google Maps Autocomplete

ChaiweiChaiwei
2 min read

Recently, while implementing a Google Maps autocomplete functionality within a React component, I stumbled upon this error.

Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

The problematic code snippet looked something like this:

/// <reference types="google.maps" />

import React, { useRef, useState, useEffect } from 'react';
import { useAutocomplete, AutocompleteProps } from '@vis.gl/react-google-maps';
import { Input, InputRef } from 'antd';

/**
 * https://visgl.github.io/react-google-maps/docs/api-reference/hooks/use-autocomplete
 * https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
 */

interface PlacesAutocompleteProps {
    onPlaceSelect?: (place: google.maps.places.PlaceResult | null) => void;
}

const PlacesAutocomplete = ({ onPlaceSelect }:PlacesAutocompleteProps) => {

    const inputRef = useRef<InputRef>(null);
    const [inputValue, setInputValue] = useState<string>('');

    const onPlaceChanged = (place: google.maps.places.PlaceResult | null) => {
        if (place) {
            setInputValue(place.formatted_address || place.name || '');
            onPlaceSelect && onPlaceSelect(place);
            console.log(place)
        }
    };

    const autocompleteOptions: AutocompleteProps = {
        inputField: inputRef.current?.input || null,
        options: {
            componentRestrictions: { country: ["us", "ca"] },
            fields: ["formatted_address", "address_components", "geometry"],
            types: ["address"],
        },
        onPlaceChanged,
    };

    useAutocomplete(autocompleteOptions);

    const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(event.target.value);
    };

    return (
        <Input ref={inputRef} value={inputValue} onChange={handleInputChange} />
    );
};

export default PlacesAutocomplete;

The problem became apparent when I discovered that the error was triggered by a particular section within the component.

Identifying the Culprit

After thorough debugging, I successfully identified the root cause of the problem: the configuration options for Google Maps autocomplete were defined within the component body.

It was due to the options object being defined inside the component and potentially causing unnecessary re-renders. To resolve this issue, we'll want to define options outside the component to prevent re-creation of the object on each render. This way, the useEffect won't consider options as a dependency triggering re-renders.

Resolving the Error:

The solution was straightforward, I defined the options as a constant outside the component's scope, and now it no longer triggers re-renders."

// Defined outside the component
const options = {
  componentRestrictions: { country: ["us", "ca"] },
  fields: ["address_components", "geometry"],
  types: ["address"],
};

const PlacesAutocomplete = ({ onPlaceSelect }:PlacesAutocompleteProps) => {

    const inputRef = useRef<InputRef>(null);
    const [inputValue, setInputValue] = useState<string>('');

    const onPlaceChanged = (place: google.maps.places.PlaceResult | null) => {
        if (place) {
            setInputValue(place.formatted_address || place.name || '');
            onPlaceSelect && onPlaceSelect(place);
            console.log(place)
        }
    };

    const autocompleteOptions: AutocompleteProps = {
        inputField: inputRef.current?.input || null,
        options: options, // move the declaration outside of the component
        onPlaceChanged,
    };

    useAutocomplete(autocompleteOptions);

    const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(event.target.value);
    };

    return (
        <Input ref={inputRef} value={inputValue} onChange={handleInputChange} />
    );
};

export default PlacesAutocomplete;
0
Subscribe to my newsletter

Read articles from Chaiwei directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chaiwei
Chaiwei