Skip to main content

Form Elements

The Easy React Native SDK provides secure form elements for PCI-compliant payment data collection. These elements ensure your application never touches sensitive payment information.

Available Elements

import {
CardNumberElement, // Card number only
CardExpirationDateElement, // Expiration date only
CardVerificationCodeElement, // CVV only
TextElement, // Bank account numbers, routing numbers
} from "@easylabs/react-native";
info

React Native SDK uses separate card elements. There is no combined CardElement like in the web SDK.

CardNumberElement

Secure input for card numbers with automatic formatting and validation.

Usage

import { CardNumberElement } from "@easylabs/react-native";
import { useRef } from "react";
import { View, Text, StyleSheet } from "react-native";

function PaymentForm() {
const cardNumberRef = useRef(null);

return (
<View>
<Text style={styles.label}>Card Number</Text>
<CardNumberElement
btRef={cardNumberRef}
placeholder="4242 4242 4242 4242"
style={styles.input}
/>
</View>
);
}

const styles = StyleSheet.create({
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
});

Props

  • btRef (required) - React ref to access the element (note: use btRef, not ref)
  • placeholder - Placeholder text
  • style - React Native StyleSheet object
  • editable - Whether the input is editable (default: true)

CardExpirationDateElement

Secure input for card expiration dates with automatic formatting.

Usage

import { CardExpirationDateElement } from "@easylabs/react-native";
import { useRef } from "react";
import { View, Text, StyleSheet } from "react-native";

function PaymentForm() {
const expiryRef = useRef(null);

return (
<View>
<Text style={styles.label}>Expiration Date</Text>
<CardExpirationDateElement
btRef={expiryRef}
placeholder="MM/YY"
style={styles.input}
/>
</View>
);
}

const styles = StyleSheet.create({
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
});

CardVerificationCodeElement

Secure input for CVV/CVC codes.

Usage

import { CardVerificationCodeElement } from "@easylabs/react-native";
import { useRef } from "react";
import { View, Text, StyleSheet } from "react-native";

function PaymentForm() {
const cvcRef = useRef(null);

return (
<View>
<Text style={styles.label}>CVC</Text>
<CardVerificationCodeElement
btRef={cvcRef}
placeholder="123"
style={styles.input}
/>
</View>
);
}

const styles = StyleSheet.create({
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
});

TextElement

General purpose secure text input for sensitive data like bank account numbers.

Usage

import { TextElement } from "@easylabs/react-native";
import { useRef } from "react";
import { View, Text, StyleSheet } from "react-native";

function BankAccountForm() {
const accountRef = useRef(null);
const routingRef = useRef(null);

return (
<View>
<Text style={styles.label}>Routing Number</Text>
<TextElement
btRef={routingRef}
placeholder="123456789"
style={styles.input}
/>

<Text style={styles.label}>Account Number</Text>
<TextElement
btRef={accountRef}
placeholder="0123456789"
style={styles.input}
/>
</View>
);
}

const styles = StyleSheet.create({
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
marginTop: 16,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
});

Complete Payment Form

Example with all card elements together:

import {
CardNumberElement,
CardExpirationDateElement,
CardVerificationCodeElement,
useEasy,
} from "@easylabs/react-native";
import { useRef, useState } from "react";
import { View, Text, Button, StyleSheet, ScrollView } from "react-native";

function CompletePaymentForm() {
const { checkout } = useEasy();
const cardNumberRef = useRef(null);
const expiryRef = useRef(null);
const cvcRef = useRef(null);
const [loading, setLoading] = useState(false);

const handleSubmit = async () => {
setLoading(true);

try {
const result = await checkout({
customer_creation: true,
customer_details: {
first_name: "John",
last_name: "Doe",
email: "[email protected]",
},
source: {
type: "PAYMENT_CARD",
cardNumberElement: cardNumberRef,
cardExpirationDateElement: expiryRef,
cardVerificationCodeElement: cvcRef,
name: "Primary Card",
},
line_items: [{ price_id: "price_123", quantity: 1 }],
});

console.log("Payment successful!", result);
} catch (err) {
console.error("Payment failed:", err);
} finally {
setLoading(false);
}
};

return (
<ScrollView style={styles.container}>
<Text style={styles.title}>Payment Information</Text>

<Text style={styles.label}>Card Number</Text>
<CardNumberElement
btRef={cardNumberRef}
placeholder="4242 4242 4242 4242"
style={styles.input}
/>

<View style={styles.row}>
<View style={styles.column}>
<Text style={styles.label}>Expiration</Text>
<CardExpirationDateElement
btRef={expiryRef}
placeholder="MM/YY"
style={styles.input}
/>
</View>

<View style={styles.column}>
<Text style={styles.label}>CVC</Text>
<CardVerificationCodeElement
btRef={cvcRef}
placeholder="123"
style={styles.input}
/>
</View>
</View>

<Button
title={loading ? "Processing..." : "Pay Now"}
onPress={handleSubmit}
disabled={loading}
/>
</ScrollView>
);
}

const styles = StyleSheet.create({
container: {
padding: 20,
},
title: {
fontSize: 24,
fontWeight: "bold",
marginBottom: 24,
},
label: {
fontSize: 16,
fontWeight: "600",
marginBottom: 8,
marginTop: 16,
},
input: {
borderWidth: 1,
borderColor: "#ccc",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
row: {
flexDirection: "row",
gap: 12,
},
column: {
flex: 1,
},
});

Styling

Basic Styling

Apply styles using React Native StyleSheet:

const styles = StyleSheet.create({
input: {
borderWidth: 1,
borderColor: "#e0e0e0",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#ffffff",
},
});

<CardNumberElement btRef={cardRef} style={styles.input} />;

Focus States

Handle focus states manually:

import { useState } from "react";

function PaymentForm() {
const [isFocused, setIsFocused] = useState(false);

return (
<CardNumberElement
btRef={cardRef}
style={[styles.input, isFocused && styles.inputFocused]}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
);
}

const styles = StyleSheet.create({
input: {
borderWidth: 1,
borderColor: "#e0e0e0",
},
inputFocused: {
borderColor: "#007AFF",
borderWidth: 2,
},
});

Dark Mode

Support dark mode:

import { useColorScheme } from "react-native";

function PaymentForm() {
const colorScheme = useColorScheme();
const isDark = colorScheme === "dark";

return (
<CardNumberElement
btRef={cardRef}
style={[styles.input, isDark ? styles.inputDark : styles.inputLight]}
/>
);
}

const styles = StyleSheet.create({
input: {
borderWidth: 1,
borderRadius: 8,
padding: 12,
fontSize: 16,
},
inputLight: {
backgroundColor: "#ffffff",
borderColor: "#e0e0e0",
color: "#000000",
},
inputDark: {
backgroundColor: "#1c1c1e",
borderColor: "#38383a",
color: "#ffffff",
},
});

Best Practices

1. Always Use btRef

Use btRef prop instead of ref for secure form elements:

// ✅ Correct
<CardNumberElement btRef={cardRef} />

// ❌ Wrong
<CardNumberElement ref={cardRef} />

2. Validate Before Submission

Check that refs are set before processing:

const handleSubmit = async () => {
if (!cardNumberRef.current || !expiryRef.current || !cvcRef.current) {
Alert.alert("Error", "Please fill in all card details");
return;
}

await checkout({...});
};

3. Provide Clear Labels

Always label your form elements:

<Text style={styles.label}>Card Number</Text>
<CardNumberElement btRef={cardRef} />

4. Handle Keyboard

Manage keyboard behavior:

import { KeyboardAvoidingView, Platform } from "react-native";

<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.container}
>
{/* Form elements */}
</KeyboardAvoidingView>;

5. Accessibility

Add accessibility props:

<Text style={styles.label} accessibilityLabel="Card number input">
Card Number
</Text>
<CardNumberElement
btRef={cardRef}
accessibilityLabel="Enter your card number"
accessibilityHint="16 digit card number"
/>

Next Steps