You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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',
    },
});

关键修正说明

  1. 用useState管理索引:把let i = 0改成const [currentIndex, setCurrentIndex] = useState(0),让索引值被React状态系统保存,组件重渲染时不会丢失。
  2. 函数式更新state:setData(prevData => [...prevData, newWeatherItem]),因为setData是异步操作,函数式更新能确保基于最新的data状态修改,避免状态覆盖。
  3. 正确设置key:将key添加到每个天气面板的外层<View>上,用dates[currentIndex]作为唯一标识(如果dates值唯一),也可用currentIndex(但如果后续有删除操作,推荐用更稳定的唯一值)。
  4. 移除全局数组:直接通过setData管理渲染数据,不再依赖全局的weatherPanel,确保状态完全由React管控。
  5. 防越界判断:添加if (currentIndex >= dates.length) return;,避免点击次数超过数组长度时报错。

内容的提问来源于stack exchange,提问作者Parth Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 02:05:22