使用map方法渲染数组时,如何让useState仅作用于单个选中项
你现在的问题核心是所有日期条目共用了同一个布尔类型的selected状态,修改这个状态自然会同步作用到所有条目上。你需要用数组类型的状态单独记录每个条目的选中情况,具体修改方式如下:
第一步:调整状态结构
把原来的布尔类型状态修改为布尔数组,长度和星期数组保持一致,初始全部为未选中:
// 若不需要TS类型标注去掉<boolean[]>即可 const [selected, setSelected] = useState<boolean[]>(new Array(dayOfWeek.length).fill(false))
另外你提供的星期数组里周二的拼写有误,"Tus"建议修正为"Tue"。
第二步:简化子组件逻辑,把选中状态的更新逻辑收敛到父组件
修改DateItem组件,不再接收setSelected,改为接收父组件传入的点击回调即可:
const DateItem = (props: DateItemProps) => { const { days, selected, onPress } = props return ( <TouchableOpacity row center onPress={onPress} style={!selected ? CONTAINER_WITHOUT_SELECTED : CONTAINER_WITH_SELECTED} > <Text style={!selected ? TEXT_WITHOUT_SELECTED : TEXT_WITH_SELECTED}>{days}</Text> {selected && <Icon name="check" color="white" />} </TouchableOpacity> ) } export default DateItem
记得同步修改DateItemProps的类型定义,把setSelected替换为onPress: () => void。
第三步:修改列表渲染逻辑,为每个条目绑定独立的点击处理
渲染时给每个条目传入对应下标的选中状态,点击时只修改对应下标的状态值,同时补充map循环必需的key属性避免React抛出警告:
<View row style={{ flexWrap: "wrap" }}> {dayOfWeek.map((item, index) => ( <View key={index}> <DateItem days={item} selected={selected[index]} onPress={() => { // 拷贝原数组避免直接修改状态,符合React不可变数据原则 const newSelected = [...selected] // 仅翻转当前点击条目的选中状态 newSelected[index] = !newSelected[index] setSelected(newSelected) }} /> </View> ))} </View>
如果你的需求是单选(同一时间只能选中一个条目),可以把状态简化为存储选中条目的下标,初始值设为-1,点击时直接把状态赋值为当前点击的下标,选中判断逻辑改为selected === index即可。
内容的提问来源于stack exchange,提问作者CODEforDREAM
相关产品推荐
相关产品推荐

