Skip to main content

Overview

The SearchBar component provides a comprehensive filtering interface for cryptocurrencies. It includes three input fields:
  1. Text search: Search by cryptocurrency name or symbol
  2. Minimum price: Filter cryptocurrencies above a certain price
  3. Maximum price: Filter cryptocurrencies below a certain price
The component uses debouncing (300ms delay) to optimize performance by reducing the number of search callbacks triggered while the user is typing.

Props

Callback function invoked when the search filter changes. Called after a 300ms debounce delay.The Filter object contains:
  • text (string): The search query text
  • minPrice (number | null): Minimum price filter, or null if not set
  • maxPrice (number | null): Maximum price filter, or null if not set

Filter Interface

interface Filter {
  text: string;
  minPrice: number | null;
  maxPrice: number | null;
}

Usage Example

Basic Usage

import { useState } from 'react';
import SearchBar from './components/SearchBar';

function CryptoSearch() {
  const handleSearch = (filter) => {
    console.log('Search text:', filter.text);
    console.log('Min price:', filter.minPrice);
    console.log('Max price:', filter.maxPrice);
    
    // Apply filtering logic here
  };

  return <SearchBar onSearch={handleSearch} />;
}

With Filter Context

Typically used with a filter context to share search state across components:
import SearchBar from './components/SearchBar';
import { useFilter } from '../context/FilterContext';

function Header() {
  const { setFilter } = useFilter();
  
  return <SearchBar onSearch={setFilter} />;
}

Filtering Cryptocurrency Data

import { useState, useEffect } from 'react';
import SearchBar from './components/SearchBar';

function FilteredCryptoList({ cryptos }) {
  const [filtered, setFiltered] = useState(cryptos);

  const handleSearch = (filter) => {
    const result = cryptos.filter(crypto => {
      const matchesText = 
        crypto.name.toLowerCase().includes(filter.text.toLowerCase()) ||
        crypto.symbol.toLowerCase().includes(filter.text.toLowerCase());
      
      const price = parseFloat(crypto.price_usd);
      const matchesMinPrice = filter.minPrice ? price >= filter.minPrice : true;
      const matchesMaxPrice = filter.maxPrice ? price <= filter.maxPrice : true;
      
      return matchesText && matchesMinPrice && matchesMaxPrice;
    });
    
    setFiltered(result);
  };

  return (
    <>
      <SearchBar onSearch={handleSearch} />
      {/* Render filtered list */}
    </>
  );
}

Component Behavior

Debouncing

The component implements a 300ms debounce to prevent excessive callback invocations:
useEffect(() => {
  const timeout = setTimeout(() => {
    onSearch({
      text,
      minPrice: minPrice ? minPrice : null,
      maxPrice: maxPrice ? maxPrice : null,
    });
  }, 300);

  return () => clearTimeout(timeout);
}, [text, minPrice, maxPrice]);
Benefits:
  • Reduces API calls or filtering operations
  • Improves performance during rapid typing
  • Provides smoother user experience

Input Handling

Direct string state:
const [text, setText] = useState('');

<TextInput
  placeholder="Buscar criptomoneda..."
  value={text}
  onChangeText={setText}
  style={styles.input}
/>
  • Accepts any text input
  • Case-insensitive search (handled by parent)
  • No validation or formatting

Styling Details

Container

container: {
  backgroundColor: '#fff',
  padding: 12,
  borderRadius: 12,
  marginBottom: 16,
  shadowColor: '#000',
  shadowOffset: { width: 0, height: 2 },
  shadowOpacity: 0.1,
  shadowRadius: 6,
  elevation: 4,
}
  • White background with subtle shadow for elevation
  • 12px padding and border radius for rounded appearance
  • 16px bottom margin for spacing from content below
  • Platform-specific shadows (iOS) and elevation (Android)

Input Fields

input: {
  fontSize: 16,
  color: '#333',
  borderWidth: 1,
  marginBottom: 5,
  marginTop: 5,
  borderColor: '#ddd',
  paddingHorizontal: 12,
  paddingVertical: 8,
  borderRadius: 8,
}
  • Light gray border (#ddd) with 1px width
  • 16px font size for readability
  • 8px vertical spacing between inputs
  • 8px border radius for consistent rounded corners
  • Adequate padding for touch targets

Visual Layout

┌─────────────────────────────────────┐
│  ┌───────────────────────────────┐  │
│  │ Buscar criptomoneda...        │  │ ← Text search
│  └───────────────────────────────┘  │
│  ┌───────────────────────────────┐  │
│  │ Precio mínimo                 │  │ ← Min price
│  └───────────────────────────────┘  │
│  ┌───────────────────────────────┐  │
│  │ Precio máximo                 │  │ ← Max price
│  └───────────────────────────────┘  │
└─────────────────────────────────────┘

Performance Optimization

The 300ms debounce delay is crucial for performance. Without it, every keystroke would trigger the onSearch callback, potentially causing excessive re-renders or API calls.

Cleanup Function

The useEffect hook properly cleans up timeouts to prevent memory leaks:
return () => clearTimeout(timeout);
This ensures that if the user types again before the 300ms delay completes, the previous timeout is cancelled.
  • HomeHeader: Header component that integrates SearchBar
  • CryptoList: List component that displays filtered results
  • CryptoCard: Individual card component for each cryptocurrency

Source Code Location

~/workspace/source/src/components/SearchBar.tsx:30

Build docs developers (and LLMs) love