ErrorPro / react-google-autocomplete

React components for google places API.
MIT License
473 stars 114 forks source link

Ref prop is not updated when the component is recreated #170

Open MoritzKn opened 2 years ago

MoritzKn commented 2 years ago

When the component is rendered conditionally, it will create a new input element every time it renders again. However, the ref prop is only reassigned if it is empty and is therefore not updated:

https://github.com/ErrorPro/react-google-autocomplete/blob/214a7c3d4740d2bfcf85264717b0e0da5bd0b333/src/usePlacesWidget.js#L54

This is also an issue for the workaround of https://github.com/ErrorPro/react-google-autocomplete/issues/169

Reproduction Example

function MyComponent() {
  const inputRef = useRef(null);
  const [visible, setVisible] = useState(false);

  return (
    <>
      <button type="button" onClick={() => setVisible(!visible)}>
        Toggle
      </button>

      <button
        type="button"
        onClick={() => {
          if (inputRef && inputRef.current) {
            inputRef.current.value = "";
          }
        }}
      >
        Reset
      </button>

      {!visible && (
        <Autocomplete
          apiKey={YOUR_GOOGLE_MAPS_API_KEY}
          ref={inputRef}
          onPlaceSelected={(place) => console.log(place)}
        />
      )}
    </>
  );
}

Once you toggled the component once, the reset will be broken. This is because the inputRef will still refer to the old input element.

Workaround

Manually set the ref back to null:

      <button
        type="button"
        onClick={() => {
          setVisible(!visible);
          // This fixes the issue
          inputRef.current = null;
        }}
      >
        Toggle
      </button>
ErrorPro commented 2 years ago

Yeah, that's indeed the case. I'll try to see if there's a way to fix it. Probably comparing the refs between renders and reassiging if they differ would make it work.