Hi everyone, In this article we are going to learn about implementing Udyam Number Masking and Validation in React Native App. While building React Native applications that collect Udyam Registration Numbers (URN), it is important to ensure that user input strictly follows the official format.
This article demonstrates a practical React Native implementation that provides:
-
Real-time Udyam number masking
-
Fixed
UDYAM-prefix handling -
Automatic dash insertion
-
Smooth backspace behavior
-
Regex-based validation
-
Clean and reusable source code
1. Udyam Registration Number Format
Official format:
UDYAM-AA-00-0000000
Format rules
-
Prefix must be
UDYAM- -
Next two characters must be uppercase alphabets
-
Next two characters must be digits
-
Last seven characters must be digits
-
Total length must be 19 characters
2. Udyam number validation Pattern Used
^UDYAM-[A-Z]{2}-\d{2}-\d{7}$
3. Features Implemented in This Example
This implementation supports:
-
Fixed
UDYAM-prefix (cannot be removed) -
Uppercase enforcement for alphabets
-
Automatic hyphen insertion while typing
-
Controlled backspace behavior
-
Input length restriction
-
Real-time validation feedback
4. Input Handling Flow
Step-by-step logic:
-
Input is initialized with
UDYAM- -
User input is accepted only after the prefix
-
Invalid characters are automatically removed
-
Text is converted to uppercase
-
Hyphens are inserted at correct positions
-
While deleting, formatting is not forced
-
Validation runs on every input change
5. Complete React Native Source Code
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* @format
*/
import { useState } from 'react';
import {
Dimensions,
StatusBar,
StyleSheet,
Text,
TextInput,
useColorScheme,
View,
} from 'react-native';
import { SafeAreaProvider } from 'react-native-safe-area-context';
export const App = () => {
const isDarkMode = useColorScheme() === 'dark';
const [udyam, setUdyam] = useState('UDYAM-');
const [prevUdyam, setPrevUdyam] = useState('');
const [udyamError, setUdyamError] = useState({});
const screeWidth = Dimensions.get('screen').width;
const formWidth = screeWidth - 60;
const commonHeaderMargin = screeWidth - formWidth;
const onTextChange = (value: string) => {
const { formattedURN, isValid } = formatAndValidateUdyam(value, prevUdyam);
console.log('++++ formattedURN.length ', formattedURN.length);
if (isValid && formattedURN.length === 19) {
setUdyamError({ error: 'Valid Udyam number', valid: true });
} else {
setUdyamError({ error: 'Please enter valid Udyam number', valid: false });
}
setPrevUdyam(value);
setUdyam(formattedURN);
};
const formatAndValidateUdyam = (value: string, prevValue: string) => {
const prefix = 'UDYAM-';
// Ensure prefix always exists
if (!value.startsWith(prefix)) {
value = prefix;
}
const isDeleting =
value.length < prevValue.length || value.length === prevValue.length;
// Extract part after prefix
let raw = value
.slice(prefix.length)
.toUpperCase()
.replace(/[^A-Z0-9]/g, '')
.slice(0, 11);
// If deleting AND previous ended with a dash -> remove 1 extra character
if (isDeleting && prevValue.endsWith('-')) {
raw = raw.slice(0, raw.length - 1);
}
let formatted = '';
if (isDeleting) {
// No auto formatting while deleting
if (raw.length <= 2) {
formatted = raw;
} else if (raw.length <= 4) {
formatted = `${raw.slice(0, 2)}-${raw.slice(2)}`;
} else {
formatted = `${raw.slice(0, 2)}-${raw.slice(2, 4)}-${raw.slice(4)}`;
}
} else {
// Auto formatting while typing
if (raw.length < 2) {
formatted = raw;
} else if (raw.length === 2) {
formatted = `${raw}-`;
} else if (raw.length === 3) {
formatted = `${raw.slice(0, 2)}-${raw.slice(2)}`;
} else if (raw.length === 4) {
formatted = `${raw.slice(0, 2)}-${raw.slice(2)}-`;
} else {
formatted = `${raw.slice(0, 2)}-${raw.slice(2, 4)}-${raw.slice(4)}`;
}
}
const finalURN = prefix + formatted;
const isValid = /^UDYAM-[A-Z]{2}-\d{2}-\d{7}$/.test(finalURN);
return { formattedURN: finalURN, isValid };
};
return (
<SafeAreaProvider>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<View style={styles.container}>
<Text
style={{
fontSize: 25,
fontWeight: 700,
textAlign: 'center',
color: 'blue',
}}
>
Techup.co.in
</Text>
<View
style={{
marginHorizontal: 30,
marginVertical: 30,
marginTop: 5,
}}
>
<Text style={{ fontSize: 25, fontWeight: 700, textAlign: 'center' }}>
Udyam number Masking and validation example
</Text>
</View>
<TextInput
onChangeText={onTextChange}
value={udyam}
style={{
width: formWidth,
height: 40,
borderRadius: 10,
borderColor: !udyamError?.valid
? 'red'
: udyamError?.valid
? 'green'
: 'grey',
borderWidth: 1,
padding: 10,
}}
/>
<View
style={{
alignSelf: 'flex-start',
width: formWidth,
marginHorizontal: 35,
marginTop: 5,
}}
>
<Text style={{ color: !udyamError?.valid ? 'red' : 'green' }}>
{udyamError?.error}
</Text>
</View>
</View>
</SafeAreaProvider>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
export default App;
6. Video Demonstration
A Video demonstration is attached at the end of this article showing:
-
Live Udyam number typing
-
Auto masking behavior
-
Backspace handling
-
Validation success and error states
This helps in quickly understanding the real-time behavior of the implementation.

