React Native中如何创建新页面并实现FlatList内宝可梦元素点击跳转?
你当前已实现的宝可梦网格列表效果如下:
需要实现的点击跳转后的详情页效果如下:
具体实现方案
你需要结合「列表项点击事件绑定」+「React Native路由能力」共同实现该需求,具体步骤如下:
1. 配置路由导航栈
React Native生态通用的路由方案是React Navigation,先完成基础依赖安装和路由配置,把宝可梦列表页、宝可梦详情页都注册到导航栈中,示例配置如下:
// 导航根文件示例 import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import PokemonList from './pages/PokemonList'; // 你现有列表页组件路径 import PokemonDetail from './pages/PokemonDetail'; // 新建的详情页组件路径 const Stack = createNativeStackNavigator(); export default function App() { return ( <NavigationContainer> <Stack.Navigator initialRouteName="PokemonList"> <Stack.Screen name="PokemonList" component={PokemonList} options={{title: '宝可梦列表'}} /> <Stack.Screen name="PokemonDetail" component={PokemonDetail} options={{title: '宝可梦详情'}} /> </Stack.Navigator> </NavigationContainer> ); }
2. 给FlatList列表项绑定点击跳转事件
不需要在FlatList根组件上绑定onPress,只需要在renderItem方法渲染的每个宝可梦卡片外层,包裹可点击组件(TouchableOpacity/Pressable均可),在点击事件中调用路由的navigate方法,同时把当前宝可梦的唯一标识(id/详情接口地址)作为参数传给详情页即可,示例代码如下:
// 列表页组件内部FlatList相关代码示例 import { FlatList, TouchableOpacity, Image, Text, View } from 'react-native'; import axios from 'axios'; import { useEffect, useState } from 'react'; export default function PokemonList({ navigation }) { // 路由自动注入navigation对象用于跳转 const [pokemonList, setPokemonList] = useState([]); useEffect(() => { // 你原有axios拉取列表数据的逻辑保持不变 axios.get('宝可梦列表接口地址').then(res => { setPokemonList(res.data.results); }) }, []); const renderPokemonItem = ({ item }) => { return ( // 给原有卡片外层包可点击组件 <TouchableOpacity style={{width: '30%', margin: '1.5%', alignItems: 'center'}} onPress={() => { // 跳转详情页,同时传递当前宝可梦的参数 navigation.navigate('PokemonDetail', { // 从接口返回的宝可梦详情url中提取id,也可直接传完整url pokemonId: item.url.split('/').filter(Boolean).pop(), pokemonName: item.name }) }} > {/* 你原有渲染宝可梦卡片的逻辑保持不变 */} <Image source={{uri: `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/${item.url.split('/').filter(Boolean).pop()}.png`}} style={{width: 80, height: 80}} /> <Text>{item.name}</Text> </TouchableOpacity> ) } return ( <FlatList data={pokemonList} renderItem={renderPokemonItem} numColumns={3} // 保持你现有三列网格布局不变 keyExtractor={(item, index) => index.toString()} /> ) }
3. 详情页接收参数渲染内容
在详情页组件中,通过路由注入的route对象获取列表页传过来的参数,之后请求详情接口渲染页面即可,示例代码如下:
// 详情页组件示例 import { View, Text, Image, StyleSheet } from 'react-native'; import { useEffect, useState } from 'react'; import axios from 'axios'; export default function PokemonDetail({ route }) { // 路由自动注入route对象用于取参 // 取出列表页传递的参数 const { pokemonId, pokemonName } = route.params; const [pokemonDetail, setPokemonDetail] = useState(null); useEffect(() => { // 请求当前宝可梦的详情数据 axios.get(`宝可梦详情接口前缀地址/${pokemonId}`).then(res => { setPokemonDetail(res.data); }) }, [pokemonId]); if(!pokemonDetail) return null; return ( <View style={styles.container}> <Image source={{uri: pokemonDetail.sprites.front_default}} style={styles.avatar} /> <Text style={styles.name}>{pokemonName}</Text> <Text>身高:{pokemonDetail.height}</Text> <Text>体重:{pokemonDetail.weight}</Text> <Text>属性:{pokemonDetail.types.map(t => t.type.name).join('、')}</Text> </View> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', padding: 20 }, avatar: { width: 200, height: 200, marginBottom: 20 }, name: { fontSize: 24, fontWeight: 'bold', marginBottom: 10 } })
小提示:如果你的列表接口已经返回了足够的详情展示数据,也可以直接把整个item对象作为参数传递给详情页,省略详情页的二次接口请求,优化加载速度。
内容的提问来源于stack exchange,提问作者mmiah
相关产品推荐
相关产品推荐

