skip to Main Content

I want to create and use a CustomTextInput in React Native. I have created it as shown in the code below, but the onChangeText prop inside the CustomTextInput is not working correctly.

Despite extensive research, I couldn’t figure out the reason behind the issue. What could I be missing?

import React, { useState } from 'react';
import { View, StyleSheet } from 'react-native';
import { TextInput } from 'react-native';


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

const CustomTextInput = ({ value, onChangeText, placeholder, style }) => {
  return (
    <TextInput
      value={value}
      onChangeText={onChangeText}
      placeholder={placeholder}
      style={style}
    />
  );
};


  const handleTextChange = (text) => {
    setInputValue(text);
  };

  return (
    <View style={styles.container}>
      <CustomTextInput
        value={inputValue}
        onChangeText={handleTextChange}
        placeholder="Custom, not working..."
        style={styles.textInput}
      />

     <TextInput
      value={inputValue}
      onChangeText={handleTextChange}
      placeholder={"Working.."}
      style={styles.textInput}
    />

    </View>

    
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f0f0f0',
  },
  textInput: {
    width: '80%',
    height: 40,
    borderWidth: 1,
    borderColor: 'gray',
    padding: 10,
  },
});

export default App;

also you can check in here
https://snack.expo.dev/@cemyeten/handling-text-input

3

Answers


  1. Put your component outside the App function or a better way is to create a separate file for it because if you put it inside when you write text useState hook re-renders the App function to reflect it on UI and it makes your component out of focus.

    Fixed code:

    import React, { useState } from 'react';
    import { View, StyleSheet } from 'react-native';
    import { TextInput } from 'react-native';
    
    const CustomTextInput = ({ value, onChangeText, placeholder, style,...other }) => {
      return (
        <TextInput
          value={value}
          onChangeText={onChangeText}
          placeholder={placeholder}
          style={style}
          {...other}
        />
      );
    };
    
    const App = () => {
      const [inputValue, setInputValue] = useState('');
    
      const handleTextChange = (text) => {
        setInputValue(text);
      };
    
      return (
        <View style={styles.container}>
          <CustomTextInput
            value={inputValue}
            onChangeText={handleTextChange}
            placeholder="Custom, not working..."
            style={styles.textInput}
          />
    
         <TextInput
          value={inputValue}
          onChangeText={handleTextChange}
          placeholder={"Working.."}
          style={styles.textInput}
        />
    
        </View>
    
        
      );
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#f0f0f0',
      },
      textInput: {
        width: '80%',
        height: 40,
        borderWidth: 1,
        borderColor: 'gray',
        padding: 10,
      },
    });
    
    export default App;
    
    Login or Signup to reply.
  2. As I can see you have created component inside the component and using it.

    But, as you are creating a functional component inside the component it will re-created every time when any state update will occur.

    Better option is to move the CustomTextInput outside the screen or any component that has state.

    Eg.

    import React, { useState } from 'react';
    import { View, StyleSheet } from 'react-native';
    import { TextInput } from 'react-native';
    
    const CustomTextInput = ({ value, onChangeText, placeholder, style }) => {
      return (
        <TextInput
          key='a'
          value={value}
          onChangeText={onChangeText}
          placeholder={placeholder}
          style={style}
        />
      );
    };
    
    const App = () => {
      const [inputValue, setInputValue] = useState('');
    
      const handleTextChange = (text) => {
        setInputValue(text);
      };
    
      return (
        <View style={styles.container}>
          <CustomTextInput
            value={inputValue}
            onChangeText={handleTextChange}
            placeholder="Custom, not working..."
            style={styles.textInput}
          />
         <TextInput
          value={inputValue}
          onChangeText={handleTextChange}
          placeholder={"Working.."}
          style={styles.textInput}
        />
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#f0f0f0',
      },
      textInput: {
        width: '80%',
        height: 40,
        borderWidth: 1,
        borderColor: 'gray',
        padding: 10,
      },
    });
    
    export default App;
    
    Login or Signup to reply.
  3. I have tested your snippet: indeed, typing in your <CustomTextInput> component unfocuses the input, which I think is what you refer to as not working correctly.

    This is because when your callback function handleTextChange() is called, it changes the value of inputValue. This will trigger a new rendering of <CustomTextInput>, which will create a new <TextInput> object, therefore deleting the previous one and thus unfocusing your input.

    Replacing

    <CustomTextInput
            value={inputValue}
            onChangeText={handleTextChange}
            placeholder="Custom, not working..."
            style={styles.textInput}
          />
    

    with

    <TextInput
            value={inputValue}
            onChangeText={handleTextChange}
            placeholder="Custom, not working..."
            style={styles.textInput}
          />
    

    should work.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search