https://github.com/anivar/react-native-omni-select
Lightweight omni-platform dropdown component for React Native — iOS, Android, and Web. By Anivar Aravind.
https://github.com/anivar/react-native-omni-select
android component cross-platform dropdown ios nextjs react-native react-native-web select typescript web
Last synced: about 2 months ago
JSON representation
Lightweight omni-platform dropdown component for React Native — iOS, Android, and Web. By Anivar Aravind.
- Host: GitHub
- URL: https://github.com/anivar/react-native-omni-select
- Owner: anivar
- License: mit
- Created: 2025-09-05T03:43:28.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2026-04-25T07:57:12.000Z (2 months ago)
- Last Synced: 2026-04-25T09:30:05.390Z (2 months ago)
- Topics: android, component, cross-platform, dropdown, ios, nextjs, react-native, react-native-web, select, typescript, web
- Language: TypeScript
- Size: 196 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# react-native-omni-select
A lightweight, omni-platform dropdown component for React Native that works everywhere - iOS, Android, and Web.
[](https://www.npmjs.com/package/react-native-omni-select)
[](https://www.npmjs.com/package/react-native-omni-select)
[](https://github.com/anivar/react-native-omni-select/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
[](https://docs.npmjs.com/generating-provenance-statements)
[](https://reactnative.dev/)
[](https://github.com/anivar/react-native-omni-select)
[](https://www.typescriptlang.org/)
[](https://bundlephobia.com/package/react-native-omni-select)
## ✨ Features
- 📦 **< 10KB** - Tiny bundle size
- 🚀 **Zero dependencies** - No bloat
- 🌍 **Omni-platform** - Works on iOS, Android, Web, and SSR
- 📝 **TypeScript native** - Full type safety with generics
- 🎨 **Customizable** - Style it your way
- 🔍 **Searchable** - Built-in search/filter
- ✅ **Single & Multi-select** - Both modes in one component
- 🎯 **Simple API** - Just 5 essential props
## 📦 Installation
```bash
npm install react-native-omni-select
```
or with Yarn:
```bash
yarn add react-native-omni-select
```
## 🚀 Quick Start
```tsx
import { Dropdown } from 'react-native-omni-select';
const MyComponent = () => {
const [value, setValue] = useState(null);
const data = [
{ label: 'Apple', value: 'apple' },
{ label: 'Banana', value: 'banana' },
{ label: 'Orange', value: 'orange' },
];
return (
);
};
```
## 📚 Examples
Check out the complete examples in the repository:
- [**Basic Examples**](https://github.com/anivar/react-native-omni-select/blob/main/example/BasicExample.tsx) - Simple dropdown usage with strings and objects
- [**Multi-Select Examples**](https://github.com/anivar/react-native-omni-select/blob/main/example/MultiSelectExample.tsx) - Multiple selection with search
- [**Custom Type Examples**](https://github.com/anivar/react-native-omni-select/blob/main/example/CustomTypeExample.tsx) - TypeScript generics and custom rendering
- [**Complete App Example**](https://github.com/anivar/react-native-omni-select/blob/main/example/App.tsx) - Full featured example app
- [**Examples Documentation**](https://github.com/anivar/react-native-omni-select/tree/main/example) - How to run the examples
## 📖 Complete Usage Guide
### 1️⃣ Basic Usage
#### Simple String Array
```tsx
import { Dropdown } from 'react-native-omni-select';
const SimpleExample = () => {
const [selected, setSelected] = useState(null);
return (
);
};
```
#### Object Array with Label/Value
```tsx
const ObjectExample = () => {
const [selected, setSelected] = useState(null);
const options = [
{ label: 'JavaScript', value: 'js' },
{ label: 'TypeScript', value: 'ts' },
{ label: 'Python', value: 'py' },
{ label: 'Ruby', value: 'rb' },
];
return (
);
};
```
### 2️⃣ Multi-Select Mode
```tsx
const MultiSelectExample = () => {
const [selectedItems, setSelectedItems] = useState([]);
const categories = ['Electronics', 'Clothing', 'Books', 'Sports', 'Home', 'Toys'];
return (
{/* Display selected items */}
{selectedItems.length > 0 && (
Selected: {selectedItems.join(', ')}
)}
);
};
```
### 3️⃣ Search/Filter Functionality
```tsx
const SearchableExample = () => {
const [country, setCountry] = useState(null);
const countries = [
{ label: 'United States', value: 'us', code: '+1' },
{ label: 'United Kingdom', value: 'uk', code: '+44' },
{ label: 'Canada', value: 'ca', code: '+1' },
{ label: 'Australia', value: 'au', code: '+61' },
// ... more countries
];
return (
);
};
```
### 4️⃣ Custom Data Types with TypeScript
```tsx
interface Product {
id: string;
name: string;
price: number;
category: string;
inStock: boolean;
}
const ProductSelector = () => {
const [product, setProduct] = useState(null);
const products: Product[] = [
{ id: '1', name: 'iPhone 15', price: 999, category: 'Electronics', inStock: true },
{ id: '2', name: 'MacBook Pro', price: 2499, category: 'Electronics', inStock: true },
{ id: '3', name: 'AirPods', price: 249, category: 'Audio', inStock: false },
];
return (
data={products}
value={product}
onChange={setProduct}
labelField="name"
valueField="id"
placeholder="Select a product"
renderItem={(item, isSelected) => (
{item.name}
${item.price}
{!item.inStock && Out of Stock}
)}
/>
);
};
```
### 5️⃣ Custom Rendering
```tsx
const CustomRenderExample = () => {
const [user, setUser] = useState(null);
const users = [
{ id: 1, name: 'John Doe', avatar: '👨', role: 'Admin' },
{ id: 2, name: 'Jane Smith', avatar: '👩', role: 'User' },
{ id: 3, name: 'Bob Johnson', avatar: '🧑', role: 'Moderator' },
];
return (
(
{user.avatar}
{user.name}
{user.role}
)}
/>
);
};
```
### 6️⃣ Platform-Specific Usage
#### React Native (iOS/Android)
```tsx
import { Dropdown } from 'react-native-omni-select';
// Works out of the box on iOS and Android
const NativeExample = () => {
const [value, setValue] = useState(null);
return (
);
};
```
#### React Native Web
```tsx
import { Dropdown } from 'react-native-omni-select';
// Automatically detects web platform
const WebExample = () => {
const [value, setValue] = useState(null);
return (
);
};
```
#### Next.js (with SSR)
```tsx
import dynamic from 'next/dynamic';
// SSR-safe import
const Dropdown = dynamic(
() => import('react-native-omni-select').then(mod => mod.Dropdown),
{
ssr: false,
loading: () =>
Loading...
}
);
const NextExample = () => {
const [value, setValue] = useState(null);
return (
);
};
```
### 7️⃣ Styling Examples
```tsx
const StyledExample = () => {
return (
<>
{/* Custom trigger button style */}
{/* Custom dropdown menu style */}
{/* Custom item style */}
>
);
};
```
### 8️⃣ Advanced Use Cases
#### Form Integration
```tsx
const FormExample = () => {
const [formData, setFormData] = useState({
name: '',
country: null,
interests: [],
});
return (
setFormData({...formData, name: text})}
placeholder="Name"
/>
setFormData({...formData, country})}
placeholder="Country"
/>
setFormData({...formData, interests})}
multiple
search
placeholder="Select interests"
/>
console.log(formData)} />
);
};
```
#### Dynamic Data Loading
```tsx
const DynamicDataExample = () => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [value, setValue] = useState(null);
useEffect(() => {
// Fetch data from API
fetchOptions().then(options => {
setData(options);
setLoading(false);
});
}, []);
if (loading) {
return ;
}
return (
);
};
```
## 🔧 API Reference
### Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `data` | `T[]` | Required | Array of items to display |
| `value` | `T \| T[] \| null` | `undefined` | Selected value(s) |
| `onChange` | `(value: T \| T[] \| null) => void` | `undefined` | Selection change handler |
| `placeholder` | `string` | `'Select'` | Placeholder text |
| `multiple` | `boolean` | `false` | Enable multi-select |
| `search` | `boolean` | `false` | Enable search/filter |
| `searchPlaceholder` | `string` | `'Search...'` | Search input placeholder |
| `disabled` | `boolean` | `false` | Disable the dropdown |
| `labelField` | `keyof T \| (item: T) => string` | `'label'` | Field/function for display text |
| `valueField` | `keyof T \| (item: T) => any` | `'value'` | Field/function for value |
| `renderItem` | `(item: T, isSelected: boolean) => ReactNode` | `undefined` | Custom item renderer |
| `style` | `ViewStyle` | `undefined` | Trigger button style |
| `dropdownStyle` | `ViewStyle` | `undefined` | Dropdown menu style |
| `itemStyle` | `ViewStyle` | `undefined` | Item container style |
| `noResultsText` | `string` | `'No results'` | Empty search results text |
## 💡 Tips & Best Practices
1. **Use TypeScript generics** for better type safety:
```tsx
data={data} ... />
```
2. **Memoize data arrays** to prevent unnecessary re-renders:
```tsx
const data = useMemo(() => [...], [dependency]);
```
3. **Handle null values** properly:
```tsx
onChange={(value) => {
if (value) {
// Handle selection
}
}}
```
4. **Optimize large lists** by implementing search:
```tsx
```
## 🏗️ Project Structure
```
react-native-omni-select/
├── src/
│ ├── Dropdown.tsx # Main component (200 lines)
│ ├── index.ts # Exports
│ └── types.ts # TypeScript definitions
├── example/ # Usage examples
│ ├── App.tsx # Basic example
│ ├── NextExample.tsx # Next.js example
│ └── WebExample.tsx # React Native Web example
├── docs/ # Additional documentation
└── package.json
```
## 🤝 Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
## 📄 License
MIT © [Anivar Aravind](https://github.com/anivar)
## 🙏 Support
If you find this package useful, please ⭐ star it on [GitHub](https://github.com/anivar/react-native-omni-select)!
☕ [Buy me a coffee](https://www.buymeacoffee.com/anivar)
---
**Why react-native-omni-select?** Simple. It works everywhere, has zero dependencies, and is under 10KB. No complexity, just a dropdown that works.