如何在useState中正确递增变量i以生成唯一key?
问题分析与解决方案
你的核心问题出在变量作用域和状态管理方式上:
- 局部变量
i每次组件渲染都会被重置为0,因为函数组件每次重渲染都会重新执行整个函数体,之前的i值不会被保留。 - 全局数组
weatherPanel不受React状态管控,即便你push元素进去,组件也不会自动重渲染,多次操作后还会导致状态混乱。 key的使用位置错误:应该给循环渲染的最外层元素(这里是每个<View style={styles.weatherBoard}>)添加唯一key,而非内部的<Text>组件。
修正后的完整代码
import React, { useState } from "react"; import { View, Text, StyleSheet, TextInput } from 'react-native'; function WeatherApp(){ // 用React状态管理当前索引和渲染数据 const [data, setData] = useState([]); const [currentIndex, setCurrentIndex] = useState(0); const dates = [1, 2, 3, 4, 5, 6, 7, 8, 9]; const temperatures = [20, 21, 26, 19, 30, 32, 23, 22, 24]; const cities = ['LA', 'SAN', 'SFO', 'LGA', 'HND', 'KIX', 'DEN', 'MUC', 'BOM']; const buttonPressed = () => { // 防止点击次数超过数组长度导致越界 if (currentIndex >= dates.length) return; // 创建单个天气面板项 const newWeatherItem = ( <View key={dates[currentIndex]} style={styles.weatherBoard}> <Text style={styles.date}>{dates[currentIndex]}</Text> <Text style={styles.temperature}>{temperatures[currentIndex]}</Text> <Text style={styles.cityName}>{cities[currentIndex]}</Text> </View> ) // 函数式更新state,确保基于最新状态修改 setData(prevData => [...prevData, newWeatherItem]); // 递增索引 setCurrentIndex(prevIndex => prevIndex + 1); } return( <View style={styles.appBackground}> <View style={styles.searchBar}> <TextInput>Text</TextInput> </View> <View style={styles.weatherPanel}> {data} </View> <View style={styles.addButton}> <Text onPress={buttonPressed} style={styles.temperature}>添加天气项</Text> </View> </View> ) } // 补充样式定义(原代码未完整提供) const styles = StyleSheet.create({ appBackground: { flex: 1, padding: 16, }, searchBar: { marginBottom: 16, padding: 8, borderWidth: 1, borderColor: '#ccc', }, weatherPanel: { flex: 1, gap: 8, }, weatherBoard: { padding: 12, backgroundColor: '#f0f0f0', borderRadius: 8, }, date: { fontSize: 16, fontWeight: '500', }, temperature: { fontSize: 20, fontWeight: 'bold', marginVertical: 4, color: '#fff', }, cityName: { fontSize: 14, color: '#666', }, addButton: { marginTop: 16, padding: 12, backgroundColor: '#2196F3', borderRadius: 8, alignItems: 'center', }, });
关键修正说明
- 用
useState管理索引:把let i = 0改成const [currentIndex, setCurrentIndex] = useState(0),让索引值被React状态系统保存,组件重渲染时不会丢失。 - 函数式更新state:
setData(prevData => [...prevData, newWeatherItem]),因为setData是异步操作,函数式更新能确保基于最新的data状态修改,避免状态覆盖。 - 正确设置
key:将key添加到每个天气面板的外层<View>上,用dates[currentIndex]作为唯一标识(如果dates值唯一),也可用currentIndex(但如果后续有删除操作,推荐用更稳定的唯一值)。 - 移除全局数组:直接通过
setData管理渲染数据,不再依赖全局的weatherPanel,确保状态完全由React管控。 - 防越界判断:添加
if (currentIndex >= dates.length) return;,避免点击次数超过数组长度时报错。
内容的提问来源于stack exchange,提问作者Parth Gupta
相关产品推荐
相关产品推荐

