react-native-google-places-autocomplete icon indicating copy to clipboard operation
react-native-google-places-autocomplete copied to clipboard

textInputProps.onChangeText() fires immediately with empty string when component mounts

Open marcaaron opened this issue 3 years ago • 6 comments

Describe the bug

This behavior of textInputProps.onChangeText() is a bit unexpected as the code here will always pass an empty string to the textInputProps.onChangeText() when the component mounts:

https://github.com/FaridSafi/react-native-google-places-autocomplete/blob/1d5515add89e9edc3b1fa90287821e522bfb0de0/GooglePlacesAutocomplete.js#L145-L153

Suppose it makes sense to do as the code says and "load the default value's search results after the view has been rendered".

Where does the "default value" come from? It doesn't seem like there is any way to set an initial value for stateText before the effect runs - but I might be missing where this happens.

When using _handleOnChangeText() we perform the unexpected side effect here:

https://github.com/FaridSafi/react-native-google-places-autocomplete/blob/1d5515add89e9edc3b1fa90287821e522bfb0de0/GooglePlacesAutocomplete.js#L558-L561

And our custom text input onChangeText is called with an empty string. Our expectation is that this would not happen and only changes made to the text input itself would trigger such events.

Reproduction - (required - issue will be closed without this)

import React,  {useState, useRef, useEffect} from 'react';
import {TextInput, View, Text} from 'react-native';
import {GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete';

const App = () => {
  const [inputValue, setInputValue] = useState('pizza');
  const ref = useRef();

  useEffect(() => {
    ref.current?.setAddressText(inputValue);
  }, []);
  return (
    <View style={{padding: 20}}>
      <GooglePlacesAutocomplete 
          ref={ref}
          textInputProps={{
            InputComp: TextInput,
            style: {borderWidth: 2, borderColor: 'red'},
            onChangeText: (value) => {
              // Always called with an empty string no matter what
              setInputValue(value);
            },
          }}
      />
      <Text>onChangeText value = {JSON.stringify(inputValue)}</Text>
    </View>
  );
}

export default App;

2021-12-03_15-43-50

https://snack.expo.dev/b6VnvlR4M

Additional context

  • Library Version: 2.4.1

  • React Native Version: 0.64.1

  • [x] iOS

  • [x] Android

  • [x] Web

If you are using expo please indicate here:

  • [ ] I am using expo

Proposed Solution

Our ultimate goal is to use this library to:

  1. Set an initial value to the underlying custom text input on init
  2. Update this value based on what is returned in textInputProps.onChangeText()

To solve this we would stop the triggering of _handleChange() when the component mounts and instead only trigger a call to _onChangeText(text). The component's onChangeText should only be triggered if the underlying component's value actually changes so those values will be useful to the developer.

To work around this, we have to "ignore" the first call to textInputProps.onChangeText() and would prefer not to use this hack.

marcaaron avatar Dec 04 '21 02:12 marcaaron

Having the same issue @FaridSafi. When I set a default value in my state and then pass that to the GooglePlacesAutoComplete component, it blanks out once the screen loads. Currently getting around it by using a useEffect hook with an empty dependency array

KrisLau avatar Apr 27 '22 16:04 KrisLau

Seems to happen on the initial render. Here's my workaround for now in case anyone is interested:

const firstRender = useRef(true);

useEffect(() => {
    firstRender.current = false;
}, []);

// then

<GooglePlacesAutocomplete
  .
  .
 textInputProps={{
          value: initialValues.address,
          onChangeText: (newText) => {
            if (!firstRender.current) {
              // some code here with newText
            }
          },
        }}
  .
  .
/>

amerikan avatar Aug 23 '22 05:08 amerikan

the best solution i found is this <GooglePlacesAutocomplete textInputProps={{ onChange(e) { onChangeText(e.nativeEvent.text); }, }}/>

youcefswoo avatar Apr 13 '24 18:04 youcefswoo

@youcefswoo this works great. even with formik. thanks!

Isaacmeedinaa avatar May 21 '24 03:05 Isaacmeedinaa

It works with @youcefswoo suggestion. Thank you!

almiavicas avatar May 30 '24 14:05 almiavicas

the best solution i found is this <GooglePlacesAutocomplete textInputProps={{ onChange(e) { onChangeText(e.nativeEvent.text); }, }}/>

youcefswoo That's insane man, thank you so much, I passed like 4 hours searching for a solution and this worked wonderlfully! Ty

Lu1815 avatar Jul 12 '24 23:07 Lu1815