Skip to main content

Handling User Input and Forms

1. Controlling TextInput

Property Description Values
value Sets the text content of the input string
onChangeText Callback function when text changes (text: string) => void
placeholder Hint text when input is empty string
multiline Allows multiple lines in input true | false
editable Enables or disables editing true | false

Example: Basic TextInput Control

<TextInput
  value={this.state.text}
  onChangeText={(text) => this.setState({ text })}
  placeholder="Enter some text"
  style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
/>

Example: Multiline TextInput

<TextInput
  multiline={true}
  numberOfLines={4}
  placeholder="Enter multiple lines"
  style={{ height: 100, borderColor: 'gray', borderWidth: 1 }}
/>

2. Handling Keyboard Events

Event Description Properties
onKeyDown Triggered when a key is pressed down key, keyCode, shiftKey
onKeyUp Triggered when a key is released key, keyCode, shiftKey

Example: Basic Key Handling

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

const KeyboardHandler = () => {
  const [input, setInput] = useState('');

  const handleKeyDown = (e) => {
    if (e.nativeEvent.key === 'Enter') {
      console.log('Enter pressed:', input);
    }
  };

  return (
    <View>
      <TextInput
        value={input}
        onChangeText={setInput}
        onKeyDown={handleKeyDown}
        placeholder="Press Enter"
      />
    </View>
  );
};

export default KeyboardHandler;
Note: Keyboard events in React Native are handled through the onKeyDown and onKeyUp props. These events are not available on all platforms (e.g., iOS may not support onKeyDown in all cases).

3. Managing Keyboard Visibility

Example: Handling Keyboard Events

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

const KeyboardExample = () => {
  const [text, setText] = useState('');
  const [isKeyboardVisible, setIsKeyboardVisible] = useState(false);

  React.useEffect(() => {
    const keyboardDidShow = Keyboard.addListener('keyboardDidShow', () => {
      setIsKeyboardVisible(true);
    });
    const keyboardDidHide = Keyboard.addListener('keyboardDidHide', () => {
      setIsKeyboardVisible(false);
    });

    return () => {
      keyboardDidShow.remove();
      keyboardDidHide.remove();
    };
  }, []);

  return (
    <View style={[styles.container, isKeyboardVisible ? styles.keyboardVisible : null]}>
      <TextInput
        style={styles.input}
        value={text}
        onChangeText={setText}
        placeholder="Type something..."
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  keyboardVisible: {
    paddingBottom: 200, // Adjust as needed
  },
  input: {
    width: '80%',
    padding: 10,
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 5,
  },
});

export default KeyboardExample;
Event Description Use Case
keyboardDidShow Triggered when the keyboard is about to be shown Adjust layout or scroll position to keep input in view
keyboardDidHide Triggered when the keyboard is about to be hidden Reset layout or restore scroll position after input
keyboardWillShow Triggered before the keyboard is shown Prepare UI adjustments in advance
keyboardWillHide Triggered before the keyboard is hidden Undo UI adjustments before hiding
Note: Always remove keyboard event listeners in the cleanup function of useEffect to prevent memory leaks.

Example: Using KeyboardAvoidingView

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

const KeyboardAvoidingExample = () => {
  return (
    <KeyboardAvoidingView
      style={styles.container}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
    >
      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          placeholder="Enter text here"
        />
      </View>
    </KeyboardAvoidingView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  inputContainer: {
    padding: 20,
  },
  input: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
    borderRadius: 5,
    paddingHorizontal: 10,
  },
});

export default KeyboardAvoidingExample;

Keyboard Visibility Management Tips

  • Use Keyboard API to listen for keyboard show/hide events
  • Apply KeyboardAvoidingView to automatically adjust layout
  • Manually adjust view padding or margins when keyboard is visible
  • Always clean up event listeners to prevent memory leaks

4. Using KeyboardAvoidingView

KeyboardAvoidingView is a React Native component that automatically adjusts the position of your UI elements to prevent them from being obscured by the keyboard on mobile devices.

Property Description Default Value Platform Support
behavior Defines how the view adjusts to the keyboard. Options: height, padding, or position. height iOS, Android
keyboardVerticalOffset Adjusts the vertical offset of the view to account for status bars or other elements. 0 iOS, Android
enabled Enables or disables the keyboard avoiding behavior. true iOS, Android

Example: Basic Usage of KeyboardAvoidingView

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

const Example = () => {
  return (
    <KeyboardAvoidingView style={styles.container} behavior="padding">
      <View style={styles.inputContainer}>
        <TextInput placeholder="Enter text" style={styles.input} />
        <Text>This input will stay visible when keyboard appears</Text>
      </View>
    </KeyboardAvoidingView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  inputContainer: {
    padding: 20,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ccc',
    padding: 10,
    marginBottom: 10,
  },
});

export default Example;
Note: On Android, KeyboardAvoidingView requires the android:windowSoftInputMode attribute to be set in your app's manifest file to function correctly.
Warning: Using behavior="position" on Android may cause layout issues due to how the keyboard interacts with the view hierarchy.

5. Implementing Form Validation

Example: Basic Form Validation with useState

import React, { useState } from 'react';

const FormValidation = () => {
  const [formData, setFormData] = useState({
    name: '',
    email: ''
  });

  const [errors, setErrors] = useState({});

  const validate = () => {
    const newErrors = {};
    if (!formData.name.trim()) {
      newErrors.name = 'Name is required';
    }
    if (!formData.email.trim()) {
      newErrors.email = 'Email is required';
    } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
      newErrors.email = 'Invalid email format';
    }
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData({
      ...formData,
      [name]: value
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (validate()) {
      console.log('Form submitted', formData);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        name="name"
        value={formData.name}
        onChange={handleChange}
        placeholder="Name"
      />
      {errors.name && <span style={{ color: 'red' }}>{errors.name}</span>}
      <br />
      <input
        type="email"
        name="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="Email"
      />
      {errors.email && <span style={{ color: 'red' }}>{errors.email}</span>}
      <br />
      <button type="submit">Submit</button>
    </form>
  );
};

export default FormValidation;
Property Description Example
name Form field name used for validation and submission name
value Current value of the input field 'John Doe'
onChange Event handler to update form state (e) => setFormData({...formData, [e.target.name]: e.target.value})
errors Object containing validation error messages { name: 'Name is required' }
Note: Validation logic should be consistent between client and server-side to ensure data integrity.
Warning: Client-side validation can be bypassed. Always validate on the server.

Form Validation Best Practices

  • Validate input on both client and server side
  • Provide real-time feedback to users
  • Use clear and actionable error messages
  • Implement proper state management for form fields

6. Handling Multi-line Input

Property Description Usage
multiline Enables multi-line input in TextInput multiline={true}
numberOfLines Controls the number of visible lines numberOfLines={3}
maxHeight Sets maximum height for the input area maxHeight={200}

Example: Multi-line Text Input

<TextInput
  multiline={true}
  numberOfLines={4}
  maxHeight={200}
  placeholder="Enter multi-line text"
  style={{
    height: 100,
    borderColor: "gray",
    borderWidth: 1,
    padding: 10
  }}
/>
Note: Use numberOfLines to control initial visible lines and maxHeight to prevent overflow.

7. Using Secure Text Entry

Property Values Description
secureTextEntry true | false When set to true, the input field obscures text (e.g., for passwords). Default is false.

Example: Secure Password Input

<TextInput
  placeholder="Enter password"
  secureTextEntry={true}
  />
Note: secureTextEntry is supported on both iOS and Android, but behavior may vary slightly between platforms.

8. Implementing Auto-focus and Tab Navigation

Example: Auto-focusing a TextInput on Component Mount

<TextInput
  ref={inputRef}
  placeholder="Enter text"
  autoFocus={true}
/>
Property Values Description
autoFocus true | false Whether the input should receive focus on mount
onSubmitEditing Function Callback when the user submits the input (e.g., presses Enter)

Example: Managing Tab Navigation Between Inputs

<View>
  <TextInput
    ref={firstInputRef}
    placeholder="First input"
    onSubmitEditing={() => secondInputRef.current?.focus()}
  />
  <TextInput
    ref={secondInputRef}
    placeholder="Second input"
    onSubmitEditing={() => thirdInputRef.current?.focus()}
  />
  <TextInput
    ref={thirdInputRef}
    placeholder="Third input"
  />
</View>
Note: Use ref.current?.focus() to programmatically focus inputs. Ensure refs are properly initialized.

Best Practices for Auto-focus and Tab Navigation

  • Use autoFocus sparingly and only when necessary for UX.
  • Implement onSubmitEditing to handle Enter key submission.
  • Use ref to manage focus between inputs in forms.

9. Handling Input Masking

Property Description Usage
inputMask Applies a mask to an input field to enforce formatting (e.g., phone number, date) inputMask="(999) 999-9999"
maskType Defines the type of mask to apply (e.g., phone, date) maskType="phone"

Example: Phone Number Input with Mask

import { TextInput } from 'react-native';

<TextInput
  placeholder="Enter phone number"
  inputMask="(999) 999-9999"
  maskType="phone"
  keyboardType="phone-pad"
/>
Note: The inputMask property is not part of the standard React Native API. You may need to use a third-party library like react-native-input-mask.

Comparison: Manual vs Library-Based Masking

  • Manual: Requires custom logic to format and validate input
  • Library-Based: Provides pre-built mask patterns and validation

10. Managing Form State

Property Description Usage
useState React hook for managing local component state const [value, setValue] = useState('');
useReducer Alternative to useState for complex state logic const [state, dispatch] = useReducer(reducer, initialState);
useForm Custom hook for form state management (e.g., from react-hook-form) const { register, handleSubmit } = useForm();

Example: Basic form with useState

import React, { useState } from 'react';\n\nfunction MyForm() {\n  const [name, setName] = useState('');\n  const [email, setEmail] = useState('');\n\n  const handleSubmit = (e) => {\n    e.preventDefault();\n    console.log({ name, email });\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input\n        type="text"\n        value={name}\n        onChange={(e) => setName(e.target.value)}\n        placeholder="Name"\n      />\n      <input\n        type="email"\n        value={email}\n        onChange={(e) => setEmail(e.target.value)}\n        placeholder="Email"\n      />\n      <button type="submit">Submit</button>\n    </form>\n  );\n}

Example: Using useReducer for form state

import React, { useReducer } from 'react';\n\nconst formReducer = (state, action) => {\n  switch (action.type) {\n    case 'SET_FIELD':\n      return { ...state, [action.field]: action.value };\n    case 'RESET_FORM':\n      return action.initialState;\n    default:\n      return state;\n  }\n};\n\nfunction MyForm() {\n  const initialState = { name: '', email: '' };\n  const [state, dispatch] = useReducer(formReducer, initialState);\n\n  const handleChange = (field, value) => {\n    dispatch({ type: 'SET_FIELD', field, value });\n  };\n\n  const handleSubmit = (e) => {\n    e.preventDefault();\n    console.log(state);\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input\n        type="text"\n        value={state.name}\n        onChange={(e) => handleChange('name', e.target.value)}\n        placeholder="Name"\n      />\n      <input\n        type="email"\n        value={state.email}\n        onChange={(e) => handleChange('email', e.target.value)}\n        placeholder="Email"\n      />\n      <button type="submit">Submit</button>\n    </form>\n  );\n}
Note: For complex forms, consider using libraries like react-hook-form or formik to simplify validation and state management.

11. Dismissing Keyboard

Example: Dismissing Keyboard on Background Tap

import React from 'react';
import { View, TouchableWithoutFeedback, Keyboard } from 'react-native';

const DismissKeyboardView = ({ children }) => (
  <TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
    <View style={{ flex: 1 }}>
      {children}
    </View>
  </TouchableWithoutFeedback>
);

export default DismissKeyboardView;
Property Description Usage
Keyboard.dismiss() Method to dismiss the active keyboard Call when user taps outside input field
Note: This approach works best when wrapped around the entire form or input container.

Was this article helpful?