React Native FlatList多位置选中状态保持问题求助
解决React Native FlatList多选保留选中状态的问题
问题根源
你当前用useState(null)定义的selectedId只能存储单个ID,每次点击新项时会覆盖旧值,导致之前选中的项被重置。要实现多选,需要用数组或对象来存储所有选中的ID。
修改方案
核心思路
将单个ID的状态改为数组,点击项时判断当前ID是否已在数组中:存在则移除(取消选中),不存在则添加(选中)。
完整修改后的代码
import React, { useState } from 'react'; import { SafeAreaView, TouchableOpacity, Image, Text, View, FlatList } from 'react-native'; const DATA = [ { id: 1, image: 'https://c0.wallpaperflare.com/preview/298/610/503/vietnam-ho-chi-minh-city-cityscape-dusk-thumbnail.jpg', title: 'Ho Chi Minh city', }, { id: 2, image: 'https://c0.wallpaperflare.com/preview/582/203/631/ha-noi-city-vietnam-lake-thumbnail.jpg', title: 'Ha Noi city', }, { id: 3, image: 'https://media.istockphoto.com/photos/sunny-beach-in-the-pearl-island-of-phu-quoc-vietnam-picture-id1307905856?b=1&k=20&m=1307905856&s=170667a&w=0&h=MMd7neh6NOOxeUUlo6eCeU49vWp7HhQXtgTw0VNjogo=', title: 'Phu Quoc island', }, { id: 4, image: 'https://media.istockphoto.com/photos/panorama-of-the-city-of-nha-trang-in-vietnam-from-drone-point-of-view-picture-id827359312?k=20&m=827359312&s=612x612&w=0&h=4QigU_O-sGaDhuFBOS_K66A4cXxc5IUoT4NrbsPw7Oo=', title: 'Nha Trang city', }, { id: 5, image: 'https://c0.wallpaperflare.com/preview/298/610/503/vietnam-ho-chi-minh-city-cityscape-dusk-thumbnail.jpg', title: 'Ho Chi Minh city', }, { id: 6, image: 'https://c0.wallpaperflare.com/preview/582/203/631/ha-noi-city-vietnam-lake-thumbnail.jpg', title: 'Ha Noi city', }, { id: 7, image: 'https://media.istockphoto.com/photos/sunny-beach-in-the-pearl-island-of-phu-quoc-vietnam-picture-id1307905856?b=1&k=20&m=1307905856&s=170667a&w=0&h=MMd7neh6NOOxeUUlo6eCeU49vWp7HhQXtgTw0VNjogo=', title: 'Phu Quoc island', }, { id: 8, image: 'https://media.istockphoto.com/photos/panorama-of-the-city-of-nha-trang-in-vietnam-from-drone-point-of-view-picture-id827359312?k=20&m=827359312&s=612x612&w=0&h=4QigU_O-sGaDhuFBOS_K66A4cXxc5IUoT4NrbsPw7Oo=', title: 'Nha Trang city', }, ]; export default function App() { // 用数组存储所有选中的ID,初始为空数组 const [selectedIds, setSelectedIds] = useState([]); const handlePress = (itemId) => { setSelectedIds(prevIds => { // 判断当前ID是否已选中 if (prevIds.includes(itemId)) { // 已选中则移除 return prevIds.filter(id => id !== itemId); } else { // 未选中则添加 return [...prevIds, itemId]; } }); }; const renderView = ({item}) => ( <TouchableOpacity onPress={() => handlePress(item.id)} style={{ marginBottom:15, marginHorizontal:7, width:'46%', height:200, }} > <Image style={{width:'100%',height:'100%', borderRadius:20}} source={{uri:item.image}} /> <Text style={{position:'absolute',bottom:0,padding:15,color:'yellow', fontWeight:'bold'}}> {item.title} </Text> <View style={{ position:'absolute', right:0, padding:15, }}> { selectedIds.includes(item.id) ? <Text style={{fontWeight:'bold',color:'red'}}>Checked</Text> : <Text style={{fontWeight:'bold',color:'red'}}>Not check</Text> } </View> </TouchableOpacity> ); return ( <SafeAreaView style={{flex:1}}> <View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 15, paddingVertical: 10 }}> <View style={{ height:44, width:44, backgroundColor:'green', alignItems:'center', justifyContent:'center', borderRadius:30, }}> <Text style={{fontSize:25,color:'white'}}>=</Text> </View> <Text style={{fontSize:25,color:'blue',fontWeight:'bold'}}>Packages</Text> <View style={{ height:44, width:44, backgroundColor:'green', alignItems:'center', justifyContent:'center', borderRadius:30, }}> <Text style={{fontSize:25,color:'white'}}>@</Text> </View> </View> <View style={{ marginVertical:10, flex:1, paddingHorizontal: 15 }}> <FlatList data={DATA} showsVerticalScrollIndicator={false} numColumns={2} renderItem={renderView} keyExtractor={(item) => item.id.toString()} /> </View> </SafeAreaView> ); }
关键修改点
- 状态从单个
selectedId改为数组selectedIds,存储所有选中项的ID - 新增
handlePress函数,实现选中/取消选中的切换逻辑 - 渲染时通过
selectedIds.includes(item.id)判断当前项的选中状态 - 优化
keyExtractor,改用item.id而非索引,避免数据更新时的渲染异常
内容的提问来源于stack exchange,提问作者Kedo
相关产品推荐
相关产品推荐

