Overview
The cryptocurrency list view is the main interface for browsing available cryptocurrencies. It displays a scrollable list of crypto cards with real-time data and supports scroll-to-top functionality for improved navigation.
Implementation
The list view is implemented in HomeScreen.tsx and uses the CryptoList component to render individual cryptocurrency cards.
HomeScreen Component
The main screen component manages the filtered cryptocurrency data and scroll behavior:
const HomeScreen = () => {
const { data , loading , error } = useCryptoData ();
const { filter } = useFilter ();
const [ scrollY , setScrollY ] = useState ( 0 );
const scrollViewRef = useRef < ScrollView >( null );
// Filter cryptocurrencies based on context filter
const filtered = data . filter (( crypto ) => {
const nameMatch = crypto . name . toLowerCase (). includes ( filter . text . toLowerCase ());
const symbolMatch = crypto . symbol . toLowerCase (). includes ( filter . text . toLowerCase ());
const minOk = filter . minPrice === null || Number ( crypto . price_usd ) >= filter . minPrice ;
const maxOk = filter . maxPrice === null || Number ( crypto . price_usd ) <= filter . maxPrice ;
return ( nameMatch || symbolMatch ) && minOk && maxOk ;
});
return (
< ScrollView
onScroll = { handleScroll }
scrollEventThrottle = { 16 }
ref = { scrollViewRef }
>
{ filtered . map (( crypto ) => (
< CryptoCard key = { crypto . id } crypto = { crypto } />
)) }
</ ScrollView >
);
};
The filtering logic combines both text search (name/symbol) and price range filters to provide a comprehensive filtering experience.
CryptoList Component
An alternative implementation using FlatList for better performance with large datasets:
const CryptoList = () => {
const { data , loading , error } = useCryptoData ();
if ( loading ) {
return (
< View style = { styles . center } >
< ActivityIndicator size = "large" color = "#00e676" />
< Text > Cargando criptomonedas... </ Text >
</ View >
);
}
if ( error ) {
return (
< View style = { styles . center } >
< Text style = { styles . errorText } > Error al cargar las criptomonedas </ Text >
</ View >
);
}
return (
< FlatList
data = { data }
keyExtractor = { ( item ) => item . id . toString () }
renderItem = { ({ item }) => < CryptoCard crypto = { item } /> }
/>
);
};
CryptoCard Component
Each cryptocurrency is displayed using the CryptoCard component, which shows:
Name and Symbol : Cryptocurrency full name and ticker symbol
Rank : Market ranking position
Current Price : USD value formatted as currency
24h Change : Percentage change with color coding (green for positive, red for negative)
const CryptoCard = ({ crypto } : Props ) => {
const router = useRouter ();
const price = parseFloat ( crypto . price_usd || '0' );
const change = parseFloat ( crypto . percent_change_24h || '0' );
const isPositive = change >= 0 ;
return (
< Pressable onPress = { () => router . push ( `/crypto/ ${ crypto . id } ` ) } >
< TouchableOpacity style = { styles . card } >
< View style = { styles . topRow } >
< View >
< Text style = { styles . name } > { crypto . name } </ Text >
< Text style = { styles . symbol } > ( { crypto . symbol } ) </ Text >
</ View >
< Text style = { styles . rank } > # { crypto . rank } </ Text >
</ View >
< View style = { styles . bottomRow } >
< Text style = { styles . price } > { formatToUSD ( price ) } </ Text >
< Text style = { [ styles . change , isPositive ? styles . positive : styles . negative ] } >
{ isPositive ? '+' : '' }{ change . toFixed ( 2 ) } % (24h)
</ Text >
</ View >
</ TouchableOpacity >
</ Pressable >
);
};
Card Styling
The crypto cards feature a dark blue background (#1c1c7e) with shadow effects for depth:
const styles = StyleSheet . create ({
card: {
backgroundColor: '#1c1c7e' ,
borderRadius: 12 ,
padding: 16 ,
marginVertical: 10 ,
shadowColor: '#000' ,
shadowOffset: { width: 0 , height: 6 },
shadowOpacity: 0.25 ,
shadowRadius: 10 ,
elevation: 5 ,
},
// ... other styles
});
The HomeScreen implements a floating button that appears when users scroll down more than 200 pixels:
const handleScroll = ( event : any ) => {
setScrollY ( event . nativeEvent . contentOffset . y );
};
const scrollToTop = () => {
if ( scrollViewRef . current ) {
scrollViewRef . current . scrollTo ({ y: 0 , animated: true });
}
};
// Render scroll-to-top button
{ scrollY > 200 && (
< TouchableOpacity style = { styles . scrollToTopButton } onPress = { scrollToTop } >
< Text style = { styles . buttonText } > ↑ </ Text >
</ TouchableOpacity >
)}
The scroll button is positioned absolutely at the bottom-right corner with a black background and uses scrollEventThrottle={16} for smooth scroll tracking at 60fps.
const styles = StyleSheet . create ({
scrollToTopButton: {
position: 'absolute' ,
bottom: 30 ,
right: 30 ,
backgroundColor: '#000' ,
padding: 10 ,
borderRadius: 30 ,
elevation: 5 ,
},
buttonText: {
color: 'white' ,
fontSize: 18 ,
fontWeight: 'bold' ,
},
});
Loading and Error States
The list view handles three states:
Loading State
Error State
Data State
{ loading && (
< ActivityIndicator
size = "large"
color = "#0000ff"
style = { styles . loader }
/>
)}
Key Features
Real-time Data : Uses useCryptoData hook to fetch live cryptocurrency data
Optimized Rendering : Choose between ScrollView (HomeScreen) or FlatList (CryptoList) based on performance needs
Interactive Cards : Each card is tappable and navigates to the detail view
Visual Feedback : Color-coded price changes (green/red) provide instant visual cues
Smooth Scrolling : Throttled scroll events ensure smooth performance
Accessibility : Large touch targets and clear visual hierarchy