React Native Support
Treege 3.0+ includes full React Native support with a dedicated renderer implementation optimized for mobile platforms.
Installation
First, install Treege and its peer dependencies:
npm install treege react-nativeOptional Dependencies
For file input support, install the optional document picker:
npm install react-native-document-pickerNote: If react-native-document-picker is not installed, the file input will gracefully degrade and show a message to the user.
Basic Usage
Import the React Native renderer:
import { TreegeRenderer } from "treege/renderer-native";
import type { Flow, FormValues } from "treege";
function App() {
const flow: Flow = {
id: "flow-1",
nodes: [
{
id: "name",
type: "input",
data: {
type: "text",
name: "fullName",
label: "Full Name",
required: true
}
},
{
id: "email",
type: "input",
data: {
type: "text",
name: "email",
label: "Email",
required: true,
pattern: "^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"
}
}
],
edges: []
};
const handleSubmit = (values: FormValues) => {
console.log("Form submitted:", values);
};
return (
<TreegeRenderer
flow={flow}
onSubmit={handleSubmit}
/>
);
}Styling
Container Styling
Customize the ScrollView and content container styles:
<TreegeRenderer
flow={flow}
onSubmit={handleSubmit}
contentContainerStyle={{
flex: 1,
justifyContent: "center",
paddingHorizontal: 16,
}}
/>Custom Components
Override default components with your own React Native implementations:
import { Text, TextInput, View } from "react-native";
import { TreegeRenderer } from "treege/renderer-native";
// An input renderer is a component receiving a single props object: `field`
// (DOM-safe props: id, name, value, placeholder, required) and `extra` (setValue,
// error, label, helperText, node, missingDependencies). On React Native, pick the
// props you need from each.
const CustomTextInput = ({ field, extra }) => {
return (
<View style={{ marginBottom: 16 }}>
<Text style={{ fontSize: 14, marginBottom: 4, fontWeight: "500" }}>
{extra.label}
</Text>
<TextInput
value={field.value}
placeholder={field.placeholder}
onChangeText={extra.setValue}
style={{
borderWidth: 1,
borderColor: extra.error ? "#ef4444" : "#d1d5db",
padding: 12,
borderRadius: 8,
fontSize: 16,
backgroundColor: "#fff"
}}
/>
{extra.error && (
<Text style={{ color: "#ef4444", fontSize: 12, marginTop: 4 }}>
{extra.error}
</Text>
)}
</View>
);
};
<TreegeRenderer
flow={flow}
components={{
inputs: {
text: CustomTextInput
}
}}
/>Supported Input Types
Fully Implemented (Vanilla React Native)
These inputs work out of the box with no additional dependencies:
- Text inputs:
text,number,textarea,password - Boolean inputs:
checkbox,switch,hidden
With Optional Dependencies
These inputs require additional packages but degrade gracefully if not installed:
file- Requiresreact-native-document-picker
Requires Custom Implementation
These inputs require you to provide custom implementations using popular React Native libraries:
-
Selection:
select,radio,autocomplete- Recommended: @react-native-picker/picker
-
Date/Time:
date,daterange,time,timerange- Recommended: react-native-date-picker
-
Location:
address- Recommended: @react-native-community/google-places-autocomplete
-
HTTP:
http- Implement using your preferred HTTP client
Example: Custom Date Picker
Here's how to implement a custom date input using react-native-date-picker:
import DatePicker from "react-native-date-picker";
import { useState } from "react";
import { View, Text, Pressable } from "react-native";
const CustomDateInput = ({ field, extra }) => {
const [open, setOpen] = useState(false);
const date = field.value ? new Date(field.value) : new Date();
return (
<View style={{ marginBottom: 16 }}>
<Text style={{ fontSize: 14, marginBottom: 4, fontWeight: "500" }}>
{extra.label}
</Text>
<Pressable
onPress={() => setOpen(true)}
style={{
borderWidth: 1,
borderColor: extra.error ? "#ef4444" : "#d1d5db",
padding: 12,
borderRadius: 8,
backgroundColor: "#fff"
}}
>
<Text>{field.value || "Select a date"}</Text>
</Pressable>
<DatePicker
modal
open={open}
date={date}
onConfirm={(date) => {
setOpen(false);
extra.setValue(date.toISOString());
}}
onCancel={() => setOpen(false)}
/>
{extra.error && (
<Text style={{ color: "#ef4444", fontSize: 12, marginTop: 4 }}>
{extra.error}
</Text>
)}
</View>
);
};
<TreegeRenderer
flow={flow}
components={{
inputs: {
date: CustomDateInput
}
}}
/>API Reference
The React Native renderer shares the same API as the web renderer, with some platform-specific additions:
Props
| Prop | Type | Default | Description |
|---|---|---|---|
flow | Flow | null | - | Decision tree to render |
onSubmit | (values: FormValues, meta?: Meta) => void | - | Form submission handler (meta includes HTTP response data) |
onChange | (values: FormValues) => void | - | Form change handler |
validate | (values, nodes) => Record<string, string> | - | Custom validation function |
initialValues | FormValues | {} | Pre-fill values to edit a record. Accepts node.id or name keys; reactive |
components | TreegeRendererComponents | - | Custom component overrides |
language | string | "en" | UI language |
validationMode | "onSubmit" | "onChange" | "onSubmit" | When to validate |
theme | "light" | "dark" | "dark" | Renderer theme |
googleApiKey | string | - | API key for address input |
headers | HttpHeaders | - | HTTP headers applied to every request |
isLoading | boolean | false | Render a loading skeleton instead of the form |
isSubmitting | boolean | false | Force the submit/continue button into its loading state (OR-ed with internal state) |
onBack | () => void | - | Called when Back is clicked on the first step; bridges to an outer flow |
style | ViewStyle | - | ScrollView style (RN only) |
contentContainerStyle | ViewStyle | - | Content container style (RN only) |
Platform-Specific Props
style: Applied to the outerScrollViewcontainercontentContainerStyle: Applied to thecontentContainerStyleof theScrollView
Best Practices
1. Provide Custom Components for Complex Inputs
For the best user experience, implement custom components for select, date, and other complex inputs using well-maintained React Native libraries.
2. Handle Keyboard Properly
Use KeyboardAvoidingView or react-native-keyboard-aware-scroll-view to ensure inputs aren't hidden by the keyboard:
import { KeyboardAvoidingView, Platform } from "react-native";
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={{ flex: 1 }}
>
<TreegeRenderer flow={flow} onSubmit={handleSubmit} />
</KeyboardAvoidingView>3. Test on Both iOS and Android
Some inputs behave differently on iOS and Android. Always test on both platforms.
4. Consider Screen Sizes
Mobile screens are smaller than desktop. Design your forms with mobile-first principles:
- Keep labels concise
- Use appropriate input types (e.g.,
numberfor numeric keyboards) - Test on different screen sizes
Differences from Web Renderer
The React Native renderer has some differences from the web version:
- Styling: Uses React Native's
StyleSheetinstead of CSS/Tailwind - Input Components: Uses React Native primitives (
TextInput,Switch, etc.) - Optional Dependencies: More dependencies are optional to keep bundle size small
- Custom Components: More inputs require custom implementations
Example Project
For a complete example, check out the React Native example in the Treege repository.
Troubleshooting
File Input Not Working
Make sure you've installed react-native-document-picker:
npm install react-native-document-picker
cd ios && pod installType Errors with Custom Components
Ensure you're importing types from the main package:
import type { TreegeRendererComponents } from "treege";Styling Issues
Remember that React Native doesn't support all CSS properties. Use React Native's StyleSheet API and refer to the React Native documentation for supported styles.