Search code examples
reactjstypescriptreact-nativeonchangereact-native-textinput

Passing UseState in React Native with typescript to Input box component and updating it onChange


I am having some problems passing the use state to a custom text input component.I want to update the state of symbol everytime a user makes a change in the input box. The use state symbol does not get updated and come back as undefined.

App.tsx

    const App = () => {
    
    const [symbol, setSymbol] = useState('AMD');
    
    
       function handleSymbolChange() {
        setSymbol(symbol);
      }
    
    return (
    <View>
      <AppTextInput placeholder="Symbol" icon="activity" value={symbol} 
      onTextInputChange= {handleSymbolChange}/>
    </View>
  );
};
    }

AppTextInput.tsx

 interface Props {
      icon: string;
      placeholder: string;
      value: string;
      onTextInputChange: any;

}

    const AppTextInput: React.FC<Props> = ({
      icon,
      placeholder,
      value,
      onTextInputChange,
    }) => {
     
       const handleChange = (e: any) => {
        onTextInputChange(e.target.value);
        console.log(e.target.value);
      };
    
      return (
        <View>
            <Icon name={icon} size={20}/>
     
          <TextInput
            style={styles.textInput}
            placeholder={placeholder}
            value={value}
            onChange={handleChange}
          />
        </View>
      );
    };

Solution

  • There are 2 reasons why your code isn't working as expected.

    The first reason is that onTextInputChange is passing back a value, e.target.value but you aren't using that value in your handleSymbolChange callback. You should probably change your handleSymbolChange function to something like this:

    function handleSymbolChange(value: string) {
      setSymbol(value);
    }
    

    The second reason is that you're not using the e argument of the onChange TextInput callback correctly. If you take a look at the docs, you will see that the onChange callback expects an object with the following properties: { nativeEvent: { eventCount, target, text} } as an argument, whereas you're using e.target.value. In order for it to work, you'll need to change it to something like this:

    import {
      NativeSyntheticEvent,
      TextInput,
      TextInputChangeEventData,
      View,
    } from 'react-native';
    
    const App = () => {
      const handleChange = ({
        nativeEvent: { text },
      }: NativeSyntheticEvent<TextInputChangeEventData>) => {
        onTextInputChange(text);
      };
    
      return (
        <View>
          <TextInput onChange={handleChange} />
        </View>
      );
    };
    

    Or use the onChangeText property instead:

    import { TextInput, View } from 'react-native';
    
    const App = () => {
      const handleChange = (text: string) => {
        onTextInputChange(text);
      };
    
      return (
        <View>
          <TextInput onChangeText={handleChange} />
        </View>
      );
    };