Dynamic Input Fields in React Native

Dynamic Input Fields in React Native

This might be a common requirement that sometimes in our forms we need to add or remove input fields dynamically and each input field needs to be attached with its corresponding value. Recently I have implemented this. We can do it in different ways. So here goes my implementation.

In order to achieve this first, I declare 2 states and 1 ref.

	// this will be attached with each input onChangeText
  const [textValue, setTextValue] = useState(''); 
	// our number of inputs, we can add the length or decrease the length
  const [numInputs, setNumInputs] = useState(1);
  // all our input fields are tracked with this array
  const refInputs = useRef<string[]>([textValue]); 

Okay, now we need a loop to iterate until our numInputs and generate the inputs that many times.

  const inputs: JSX.Element[] = [];
	for (let i = 0; i < numInputs; i ++)
	{
		inputs.push(
			<View key={i} style={{flexDirection: 'row', alignItems: 'center'}}>
				<Text>{i + 1}.</Text>
				<TextInput
					style={styles.input}
					onChangeText={value => setInputValue(i, value)}
					value={refInputs.current[i]}
					placeholder="placeholder"
				/>
        {/* To remove the input */}
				<Pressable onPress={() => removeInput(i)} style={{marginLeft: 5}}>
					<AntDesign name="minuscircleo" size={20} color="red" />
				</Pressable>
			</View>
		);
	}

and this is our render JSX.

    <ScrollView contentContainerStyle={styles.container}>
			{inputs}
			<Pressable onPress={addInput} style={styles.addButton}>
				<Text style={{color: 'white', fontWeight: 'bold'}}>+ Add a new input</Text>
			</Pressable>
			<View style={{ marginTop: 25 }}>
				<Text>You have answered:</Text>
				{refInputs.current.map((value, i) => {
					return <Text key={i} style={styles.answer}>{`${i+ 1} - ${value}`}</Text>
				})} 
			</View>
		</ScrollView>

Since initially, our numInputs is 1, we get 1 TextInput and a button to add more inputs.

Initial state.

Cool, now we need three functions.

  • setInputValue -> is to set the input fields value.
	const setInputValue = (index: number, value: string) => {
    // first, we are storing input value to refInputs array to track them
		const inputs = refInputs.current;
		inputs[index] = value;
    // we are also setting the text value to the input field onChangeText
		setTextValue(value)
	}
  • addInput -> add a new input when the add input button is pressed.
	const addInput = () => {
    // add a new element in our refInputs array
		refInputs.c urrent.push('');
    // increase the number of inputs
		setNumInputs(value => value + 1);
	}
  • removeInput -> remove input when minus icon is pressed.
	const removeInput = (i: number) => {
    // remove from the array by index value
		refInputs.current.splice(i, 1)[0];
    // decrease the number of inputs
		setNumInputs(value => value - 1);
	}

We are done! With all of these, we get the following output

Here is a working demo for you to play with.

2 Comments

  1. sarah

    hi hi. just want to ask, how to change this code from functional component into class component? ” const refInputs = useRef([textValue]); ” how to use useRef in class component?

    • Saad

      You can not use useRef inside any class component. useRef is a hook and can only be used in the functional component.

Leave a Reply

Your email address will not be published. Required fields are marked *