Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/soymatudev/Pokedex-Fleek/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The PokedexListScreen component provides a browsable list of all 151 Generation 1 Pokémon. It features smooth scroll-based animations, parallax effects, and seamless navigation to individual Pokémon details. Location: ~/workspace/source/src/features/pokedex/PokedexListScreen.js

Props

navigation
object
required
React Navigation object for screen navigation

Purpose

This screen serves as a comprehensive Pokédex browser allowing users to:
  • View all available Pokémon in a scrollable list
  • See Pokémon sprites, names, and ID numbers
  • Navigate to detailed views for any Pokémon
  • Experience smooth scroll-based animations

State Management

pokemonList
array
default:"[]"
Array of Pokémon data objects
loading
boolean
default:"true"
Indicates whether data is being fetched from PokéAPI
scrollY
Animated.Value
default:"0"
Animated value tracking vertical scroll position for parallax effects

Data Fetching

Fetches the first 151 Pokémon from PokéAPI on component mount:
useEffect(() => {
    fetch('https://pokeapi.co/api/v2/pokemon?limit=151')
        .then(res => res.json())
        .then(data => {
            const formattedList = data.results.map((item, index) => ({
                name: item.name,
                id: index + 1,
                image: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${index + 1}.png`
            }));
            setPokemonList(formattedList);
            setLoading(false);
        });
}, []);
The component uses the GitHub-hosted sprites directly rather than fetching individual Pokémon data for better performance

List Rendering

Animated FlatList

The component uses an Animated.FlatList for smooth scroll animations:
<Animated.FlatList
    data={pokemonList}
    keyExtractor={(item) => item.id.toString()}
    onScroll={Animated.event(
        [{ nativeEvent: { contentOffset: { y: scrollY } } }],
        { useNativeDriver: true }
    )}
    renderItem={renderItem}
    contentContainerStyle={styles.listPadding}
    snapToInterval={ITEM_SIZE}
    decelerationRate="fast"
/>
ITEM_SIZE
number
default:"120"
Height of each list item in pixels, used for snap-to behavior

Scroll Animations

Each list item features three coordinated animations:

1. Horizontal Translation (Parallax)

const translateX = scrollY.interpolate({
    inputRange,
    outputRange: [100, 0, 100],
    extrapolate: 'clamp',
});

2. Scale Effect

const scale = scrollY.interpolate({
    inputRange,
    outputRange: [0.8, 1.1, 0.8],
    extrapolate: 'clamp',
});

3. Opacity Fade

const opacity = scrollY.interpolate({
    inputRange,
    outputRange: [0.4, 1, 0.4],
    extrapolate: 'clamp',
});

Input Range Calculation

Animation input range is calculated relative to each item’s position:
const itemPosition = index * ITEM_SIZE;

const inputRange = [
    itemPosition - height,
    itemPosition - height / 2,
    itemPosition + height / 3,
];

List Item Rendering

Each Pokémon card displays ID, name, and sprite:
const renderItem = ({ item, index }) => {
    const itemPosition = index * ITEM_SIZE;
    
    const inputRange = [
        itemPosition - height,
        itemPosition - height / 2,
        itemPosition + height / 3,
    ];
    
    const translateX = scrollY.interpolate({
        inputRange,
        outputRange: [100, 0, 100],
        extrapolate: 'clamp',
    });
    
    const scale = scrollY.interpolate({
        inputRange,
        outputRange: [0.8, 1.1, 0.8],
        extrapolate: 'clamp',
    });
    
    const opacity = scrollY.interpolate({
        inputRange,
        outputRange: [0.4, 1, 0.4],
        extrapolate: 'clamp',
    });
    
    return (
        <Animated.View
            style={[
                styles.cardContainer,
                {
                    transform: [{ translateX }, { scale }],
                    opacity
                }
            ]}
        >
            <TouchableOpacity
                activeOpacity={0.8}
                style={styles.card}
                onPress={() => navigation.navigate('Details', { 
                    pokemonId: item.id 
                })}
            >
                <View style={styles.idContainer}>
                    <Text style={styles.idText}>
                        #{String(item.id).padStart(3, '0')}
                    </Text>
                </View>
                <Text style={styles.pokeName}>
                    {item.name.toUpperCase()}
                </Text>
                <Image 
                    source={{ uri: item.image }} 
                    style={styles.pokeImage} 
                />
            </TouchableOpacity>
        </Animated.View>
    );
};

Card Design

ID Number

Zero-padded three-digit format:
#{String(item.id).padStart(3, '0')}
// Examples: #001, #025, #151

Pokémon Name

Displayed in uppercase:
{item.name.toUpperCase()}
// Examples: BULBASAUR, PIKACHU, MEW

Sprite Image

70x70 pixel sprite from GitHub:
<Image 
    source={{ uri: item.image }} 
    style={styles.pokeImage} 
/>

Decorative Elements

Pokéball Background

Large semi-transparent Pokéball circle for visual depth:
<View style={styles.pokeballDecorator} />
Styling:
pokeballDecorator: {
    position: 'absolute',
    left: 250,
    top: height / 2 - 160,
    width: 320,
    height: 320,
    borderRadius: 160,
    borderWidth: 12,
    borderColor: 'rgba(244, 67, 54, 0.15)',
    zIndex: -1
}
Tapping any Pokémon card navigates to its detail view:
onPress={() => navigation.navigate('Details', { pokemonId: item.id })}

Loading State

Displays centered loading indicator during initial fetch:
if (loading) return (
    <View style={styles.loader}>
        <ActivityIndicator size="large" color={theme.colors.primary} />
    </View>
);

Performance Optimizations

Native Driver

All animations use the native driver for 60fps performance:
onScroll={Animated.event(
    [{ nativeEvent: { contentOffset: { y: scrollY } } }],
    { useNativeDriver: true }
)}

Snap Behavior

Smooth scroll-to-item behavior:
snapToInterval={ITEM_SIZE}
decelerationRate="fast"

Key Extractor

Efficient list rendering with unique keys:
keyExtractor={(item) => item.id.toString()}

Card Styling

Cards feature a distinctive design with left border accent:
card: {
    backgroundColor: theme.colors.surface,
    flexDirection: 'row',
    alignItems: 'center',
    padding: 12,
    borderRadius: 45,
    borderLeftWidth: 12,
    borderLeftColor: theme.colors.primary,
    width: '75%',
    elevation: 4,
    justifyContent: 'space-between',
}

Dependencies

  • react-native - Core components (Animated, FlatList, Dimensions)
  • react-native-safe-area-context - Safe area handling
  • Theme configuration for colors and styling

Usage Example

import { PokedexListScreen } from './features/pokedex/PokedexListScreen';

// In your navigation stack
<Stack.Screen 
    name="PokedexList" 
    component={PokedexListScreen}
    options={{ 
        title: 'Pokédex',
        headerStyle: { backgroundColor: theme.colors.primary }
    }}
/>

Integration with Other Screens

The PokedexListScreen integrates with:
  • DetailsScreen: Each list item navigates to detailed Pokémon information
  • Navigation Stack: Typically accessed from the main menu or home screen
// Example navigation flow
HomePokedexListDetails (pokemonId: 25)
The component is read-only and does not modify any data. All interactions result in navigation to detail views.