npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@miracore-ch/react-native-search-filter

v1.0.1

Published

A powerful and customizable React Native component for searching and filtering data with relevance scoring

Downloads

31

Readme

React Native Search Filter

A lightweight, highly customizable search component for React Native applications. Provides powerful text search capabilities with both simple and complex search algorithms.

npm license TypeScript

🌟 Features

  • 🔍 Simple and advanced search modes
  • 🎯 Configurable search relevance scoring
  • 🔤 Case-sensitive and insensitive options
  • 🔄 Search by multiple properties
  • 💎 Fuzzy search capability with Levenshtein distance
  • 🎨 Fully customizable styling
  • 📱 Works on all React Native platforms (iOS, Android, Web)
  • 🧩 TypeScript support

📦 Installation

# Using npm
npm install @miracore-ch/react-native-search-filter

# Using yarn
yarn add @miracore-ch/react-native-search-filter

🚀 Basic Usage

import React, { useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import { Search } from '@miracore-ch/react-native-search-filter';

const App = () => {
	const [data] = useState([
		                        { id: 1, name: 'John Doe', email: '[email protected]' },
		                        { id: 2, name: 'Jane Smith', email: '[email protected]' },
		                        { id: 3, name: 'Bob Johnson', email: '[email protected]' },
	                        ]);

	const [filteredData, setFilteredData] = useState(data);

	return (
		<View style={{ padding: 20 }}>
			<Search
				data={data}
				setSearchData={setFilteredData}
				searchByProperties={{
					keys: ['name', 'email']
				}}
				placeholder="Search users..."
			/>
			<FlatList
				data={filteredData}
				renderItem={({item}) => (
					<View style={{
						padding: 16,
						borderBottomWidth: 1,
						borderBottomColor: '#eee',
						width: '100%'
					}}>
						<Text style={{fontSize: 18, fontWeight: 'bold'}}>{item.id}</Text>
						<Text style={{fontSize: 16, color: '#007BFF'}}>{item.name}</Text>
						<Text style={{marginTop: 4, color: '#555'}}>{item.email}</Text>
					</View>
				)}
				keyExtractor={item => item.id.toString()}
			/>
		</View>
	);
};

export default App;

🔍 Advanced Usage

Complex Search with Relevance Scoring

import React, { useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import { Search } from '@miracore-ch/react-native-search-filter';
import { MaterialIcons } from '@expo/vector-icons'; // or your preferred icon library

class Product {
	constructor(public id: string, public title: string, public description: string, private _price: number) {}

	getDisplayInfo(): string {
		return `${this.title} - $${this._price}: ${this.description}`;
	}
}

const productsArray = [
	new Product("p1", "Laptop Pro X9", "High-performance laptop with 16GB RAM and 1TB SSD storage. Perfect for professionals.", 999),
	new Product("p2", "Smartphone Ultra", "Latest smartphone with 5G capability and stunning camera quality.", 499),
	new Product("p3", "Wireless Headphones", "Noise-cancelling bluetooth headphones with long battery life.", 129)
];

export default function AdvancedSearch() {
	const [filteredData, setFilteredData] = useState(productsArray);

	return (
		<View
			style={{
				flex: 1,
				justifyContent: "center",
				alignItems: "center",
			}}
		>
			<Search
				data={productsArray}
				searchByProperties={{
					keys: ['title', 'description', 'getDisplayInfo']
				}}
                setSearchData={results => setFilteredData(results)}
				searchIcon={<MaterialIcons name="search" size={20} color="#999"/>}
				clearIcon={<MaterialIcons name="close" size={20} color="#999"/>}
				useComplexSearch={true}
				complexOptions={{
					minRelevance: 0.005,
					sortByRelevance: true,
					limit: 0
				}}
			/>

			<FlatList
				data={filteredData}
				renderItem={({item}) => (
					<View style={{
						padding: 16,
						borderBottomWidth: 1,
						borderBottomColor: '#eee',
						width: '100%'
					}}>
						<Text style={{fontSize: 18, fontWeight: 'bold'}}>{item.title}</Text>
						<Text style={{fontSize: 16, color: '#007BFF'}}>{item.getDisplayInfo()}</Text>
						<Text style={{marginTop: 4, color: '#555'}}>{item.description}</Text>
					</View>
				)}
				keyExtractor={item => item.id}
			/>
		</View>
	);
}

Using Raw Search Results with Complex Search

When you need access to relevance scores and match details, you can use both setSearchData and setRawSearchData:

import React, { useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import { Search } from '@miracore-ch/react-native-search-filter';
import type { $SearchResult } from '@miracore-ch/react-native-search-filter';

interface Product {
  id: string;
  name: string;
  description: string;
}

const App = () => {
  const products = [
    { id: '1', name: 'Laptop', description: 'Powerful laptop for professionals' },
    { id: '2', name: 'Smartphone', description: 'Latest smartphone with great camera' },
    { id: '3', name: 'Headphones', description: 'Noise-cancelling wireless headphones' },
  ];

  // Regular filtered data for the list
  const [filteredProducts, setFilteredProducts] = useState<Product[]>(products);
  
  // Raw search results with match details and scores
  const [rawResults, setRawResults] = useState<$SearchResult<Product>[]>([]);
  
  return (
    <View style={{ padding: 20 }}>
      <Search
        data={products}
        searchByProperties={{
          keys: ['name', 'description']
        }}
        setSearchData={setFilteredProducts}
        setRawSearchData={setRawResults}
        useComplexSearch={true} // Enable complex search for relevance scoring
      />
      
      <FlatList
        data={filteredProducts}
        renderItem={({ item }) => {
          // Find corresponding raw result to access score and match details
          const rawResult = rawResults.find(r => r.item.id === item.id);
          
          return (
            <View style={{ padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }}>
              <Text style={{ fontWeight: 'bold' }}>{item.name}</Text>
              <Text>{item.description}</Text>
              
              {/* Display relevance info if available */}
              {rawResult && (
                <>
                  <Text style={{ color: 'green' }}>
                    Relevance: {(rawResult.relevanceScore * 100).toFixed(2)}%
                  </Text>
                  {rawResult.bestResult && (
                    <Text style={{ color: 'gray' }}>
                      Best Match: {rawResult.bestResult.text}
                    </Text>
                  )}
                </>
              )}
            </View>
          );
        }}
        keyExtractor={item => item.id}
      />
    </View>
  );
};

export default App;

🧩 Using the Standalone Search Logic

You can use the search logic independently from the UI component, allowing you to create your own custom search UI:

import React, { useState } from 'react';
import { View, Text, TextInput, FlatList } from 'react-native';
import { useSearch } from '@miracore-ch/react-native-search-filter';

const CustomSearchImplementation = () => {
  // Sample data
  const data = [
    { id: 1, name: 'Apple', category: 'Fruit' },
    { id: 2, name: 'Banana', category: 'Fruit' },
    { id: 3, name: 'Carrot', category: 'Vegetable' },
    // ...more data
  ];

  // State for search results
  const [searchResults, setSearchResults] = useState(data);
  // State for search query, updated by your custom component
  const [searchQuery, setSearchQuery] = useState('');

  // Use the useSearch hook
  useSearch({
    data,
    searchQuery,
    setSearchData: setSearchResults,
    searchByProperties: {
	    keys: ['name', 'category']
    },
    minSearchLength: 2,
    options: {
      caseSensitive: false,
      limit: 0
    }
  });

  return (
    <View>
      {/* Your custom search input */}
      <TextInput
        value={searchQuery}
        onChangeText={setSearchQuery}
        placeholder="Search fruits and vegetables..."
        style={{
          borderWidth: 1,
          borderColor: '#ccc',
          padding: 10,
          borderRadius: 5,
          marginBottom: 10
        }}
      />
      
      {/* Display search results */}
      <FlatList
        data={searchResults}
        keyExtractor={(item) => item.id.toString()}
        renderItem={({ item }) => (
          <Text>{item.name} - {item.category}</Text>
        )}
      />
    </View>
  );
};

export default CustomSearchImplementation;

📋 API Reference

Search Component Props ($Search)

| Prop | Type | Default | Description | |------|------|---------|-------------| | data | Array<T> | required | The data array to search through | | setSearchData | (filteredData: Array<T>) => void | required | Function to receive filtered data as a regular array | | setRawSearchData | (rawResults: $SearchResult<T>[]) => void | optional | Additional callback function to receive raw search results with relevance scoring and match details | | searchByProperties | $SearchableProperty<T> | required | Configuration for searchable properties | | inputStyle | TextStyle | undefined | Custom styles for the search input | | searchContainerStyle | ViewStyle | undefined | Custom styles for the search container | | placeholder | string | "Search..." | Placeholder text for the search input | | clearIcon | ReactElement \| null | null | Icon to clear the search input | | searchIcon | ReactElement \| null | null | Icon displayed at the start of the search input | | onChangeText | (text: string) => void | undefined | Callback when input text changes | | minSearchLength | number | 2 | Minimum text length to start searching | | limit | number | 0 | Limit the number of results (0 = no limit) | | useComplexSearch | boolean | false | Use complex search algorithm with relevance scoring | | options | $EasySearchOptionsProps | { caseSensitive: false, limit: 0 } | Options for basic search | | complexOptions | $ComplexSearchOptionsProps | { sortByRelevance: true, minRelevance: 0.2, limit: 0 } | Options for complex search |

useSearch Hook Props ($UseSearch)

| Prop | Type | Default | Description | |----------------------|-----------------------------------------|------------------------------------------------------------|-----------------------------------------------------| | data | Array<T> | required | The data array to search through | | searchQuery | string | required | The current search query | | setSearchData | (filteredData: Array<T>) => void | required | Function to receive filtered data as a regular array | | setRawSearchData | (rawResults: $SearchResult<T>[]) => void | optional | Additional callback function to receive raw search results with relevance scoring and match details | | searchByProperties | $SearchableProperty<T> | required | Configuration for searchable properties | | minSearchLength | number | 2 | Minimum text length to start searching | | useComplexSearch | boolean | false | Use complex search algorithm with relevance scoring | | options | $EasySearchOptionsProps | { caseSensitive: false, limit: 0 } | Options for basic search | | complexOptions | $ComplexSearchOptionsProps | { sortByRelevance: true, minRelevance: 0.00, limit: 0 } | Options for complex search | | onChangeText | (text: string) => void | undefined | Callback when input text changes |

Types

// Search options for basic search
export type $EasySearchOptionsProps = {
	caseSensitive?: boolean;
	limit?: number;
};
// Complex search options
export type $ComplexSearchOptionsProps = {
	minRelevance?: number;
	sortByRelevance?: boolean;
	limit?: number;
};
// Search property configuration
type $SearchableProperty<T> = {
  keys: T extends string ? [] : Array<keyof T>; // Property keys (object key, class property, class function) to search
  extractors?: Array<(item: T) => string>; // Custom extractors for complex data
};

// Search result for complex search
type $SearchResult<T> = {
  item: T; // The original item
  results: $SearchItemResult[]; // All search matches
  bestResult: $SearchItemResult; // Best matching result
  relevanceScore: number; // Overall relevance score
};

type $SearchItemResult = {
	text: string;
	relevance: number;
	matchDetails?: {
		matches: Array<{
			index: number,
			length: number
		}>;
		bestMatch: string;
	};
}

🔎 Search Algorithms

Basic Search

Uses a simple includes() method to find matches in the specified properties. Fast and efficient for simple filtering needs.

Complex Search

Employs a sophisticated algorithm that:

  1. Normalizes text (removing accents, case sensitivity)
  2. Calculates relevance based on:
    • Exact matches
    • Substring position and length
    • Word-level matches
    • Levenshtein distance (for fuzzy matching)
  3. Scores and ranks results by relevance
  4. Filters by minimum relevance threshold

🧰 Working with Raw Search Results

You can access both filtered data and detailed raw search results simultaneously using the dedicated callbacks:

// Example of using raw search results
import React, { useState } from 'react';
import { View, Text, FlatList } from 'react-native';
import { Search } from '@miracore-ch/react-native-search-filter';
import type { $SearchResult } from '@miracore-ch/react-native-search-filter';

interface Product {
  id: string;
  name: string;
  description: string;
}

const App = () => {
  const products = [
    { id: '1', name: 'Laptop', description: 'Powerful laptop for professionals' },
    { id: '2', name: 'Smartphone', description: 'Latest smartphone with great camera' },
    { id: '3', name: 'Headphones', description: 'Noise-cancelling wireless headphones' },
  ];

  // Regular filtered data
  const [filteredProducts, setFilteredProducts] = useState<Product[]>(products);
  
  // Raw search results with detailed match information
  const [rawResults, setRawResults] = useState<$SearchResult<Product>[]>([]);
  
  // Track if we have search results to show additional UI elements
  const [hasSearchResults, setHasSearchResults] = useState(false);
  
  return (
    <View style={{ padding: 20 }}>
      <Search
        data={products}
        searchByProperties={{
          keys: ['name', 'description']
        }}
        setSearchData={(filtered) => {
          setFilteredProducts(filtered);
          setHasSearchResults(filtered.length < products.length);
        }}
        setRawSearchData={setRawResults}
        useComplexSearch={true}
      />
      
      <FlatList
        data={filteredProducts}
        renderItem={({ item }) => {
          // Find the raw result for this item to display relevance info
          const rawResult = rawResults.find(r => r.item.id === item.id);
          
          return (
            <View style={{ padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }}>
              <Text style={{ fontWeight: 'bold' }}>{item.name}</Text>
              <Text>{item.description}</Text>
              
              {/* Only show relevance info when using complex search and we have results */}
              {hasSearchResults && rawResult && (
                <View>
                  <Text style={{ color: 'green' }}>
                    Relevance: {(rawResult.relevanceScore * 100).toFixed(2)}%
                  </Text>
                  <Text style={{ color: 'gray' }}>
                    Best Match: {rawResult.bestResult?.text}
                  </Text>
                </View>
              )}
            </View>
          );
        }}
        keyExtractor={item => item.id}
      />
    </View>
  );
};

export default App;

This is particularly useful for:

  • Highlighting matched text in the UI
  • Building custom relevance indicators
  • Debugging search results
  • Creating advanced filtering based on match details

🛠️ Customization

🎨 Styling Example

<Search
  searchContainerStyle={{
    backgroundColor: '#f5f5f5',
    borderRadius: 25,
    borderWidth: 1,
    borderColor: '#ddd',
    height: 50,
    paddingHorizontal: 20,
  }}
  inputStyle={{
    fontSize: 16,
    color: '#333',
    fontWeight: '500',
  }}
  placeholder="Custom styled search..."
  // Add your icons here
/>

Custom Property Extractors

For complex data structures or computed properties:

const fullNameExtractor = (item) => `${item.firstName} ${item.lastName}`;
const metadataExtractor = (item) => JSON.stringify(item.metadata);

<Search
  searchByProperties={{
    keys: ['email', 'username'],
    extractors: [fullNameExtractor, metadataExtractor]
  }}
  // Other props
/>

💯 Performance Tips

  • Use basic search mode for large data sets when complex relevance scoring isn't needed
  • Set an appropriate minSearchLength to prevent excessive filtering for short inputs
  • Apply a reasonable limit in options or complexOptions when dealing with large data sets
  • Use the complex search mode with caution on very large datasets (1000+ items) as it's more CPU intensive

🎮 Platform Support

| Platform | Support | |----------|---------| | iOS | ✅ | | Android | ✅ | | Web | ✅ |

📄 License

MIT

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.