React Native中useState首次映射数据丢失的解决方案问询
问题分析与解决方案
问题根源
你的问题出在**useState初始值的计算时机**:
initialData在组件首次挂载时就会被计算,此时如果accountList还未完成异步加载(比如从接口获取数据),所有依赖accountList的字段都会是undefined。- 当
accountList后续加载完成后,initialData不会自动重新生成,Data1状态也不会同步更新,因此首次打开模态框时数据显示异常。 - 关闭再打开模态框时,组件会被重新挂载,此时
accountList已经有了完整数据,initialData能正确生成,所以状态正常。
修复方案
通过 useEffect 监听 accountList 的变化,在数据就绪时同步更新 Data1 状态,具体步骤如下:
1. 抽离数据生成逻辑
把 initialData 的生成逻辑抽成独立函数,方便复用并做空值处理:
const generateAccountData = () => { if (!accountList) return []; return [ { id: 1, name: `${accountList.brideName || ''} ${accountList.brideSurname || ''}`, type: 'Gelin', selected: false, tlText: accountList.brideAccount?.accountTl, euroText: accountList.brideAccount?.accountEuro, dollarText: accountList.brideAccount?.accountUsd, accountHolderType: 'BRIDE' }, { id: 2, name: `${accountList.groomName || ''} ${accountList.groomSurname || ''}`, type: 'Damat', selected: false, tlText: accountList.groomAccount?.accountTl, euroText: accountList.groomAccount?.accountEuro, dollarText: accountList.groomAccount?.accountUsd, accountHolderType: 'GROOM' }, { id: 3, name: 'Ortak Hesap', type: 'Gelin & Damat ', selected: false, tlText: accountList.commonAccount?.accountTl, euroText: accountList.commonAccount?.accountEuro, dollarText: accountList.commonAccount?.accountUsd, accountHolderType: 'COMMON' }, ]; };
2. 初始化状态并监听数据变化
修改 useState 的初始化方式,通过 useEffect 在 accountList 更新时同步状态:
const [Data1, setData1] = useState<Data[]>([]); useEffect(() => { // 当accountList更新时,重新生成数据并更新状态 const newData = generateAccountData(); setData1(newData); }, [accountList]); // 依赖accountList,数据变化时触发更新
3. 优化渲染逻辑
添加数据为空时的兜底处理,避免渲染报错,同时修正原代码中的笔误:
<ScrollView showsVerticalScrollIndicator={false}> {Data1.length > 0 ? Data1.map((item, index) => { console.log('data5 ', accountList?.brideAccount?.accountTl); return ( <View key={item.id}> {/* 添加唯一key属性,符合React渲染规范 */} <PressableOpacity onPress={() => { setSelectedById(item.id); console.log('data6 ', accountList?.brideAccount?.accountTl); }}> <View style={{ paddingVertical: responsiveHeight(13), paddingHorizontal: responsiveWidth(24), borderBottomWidth: 1, borderBottomColor: '#F3F3F3', justifyContent: 'center', }}> <Text style={{ lineHeight: 22, fontFamily: Fonts.semiBoldRaleway, fontSize: 14, letterSpacing: 0.2, color: '#000', }}> {item.name} </Text> <Text style={{ lineHeight: 16, fontFamily: Fonts.regularPetrona, fontSize: 10, letterSpacing: 0.3, color: '#EA80AA', }}> {item.type} </Text> <Icon style={{ position: 'absolute', right: responsiveWidth(24), }} name={ item.selected ? 'chevron-down : feather' : 'chevron-right : feather' } size={20} color="#061937" /> </View> </PressableOpacity> {item?.selected && ( <View style={{ paddingHorizontal: responsiveWidth(24) }}> <Text>{accountList?.brideAccount?.accountTl}</Text> <CustomInput3 value={item?.name} /> <CustomInput3 leftImage={Images.tlBlack} value={item?.tlText} onChangeText={(value) => handleChangeTl(index, value)} /> <CustomInput3 leftImage={Images.dolarBlack} value={item?.dollarText} onChangeText={(value) => handleChangeDollar(index, value)} /> <CustomInput3 leftImage={Images.euroBlack} value={item.euroText} onChangeText={(value) => handleChangeEuro(index, value)} /> <CButton text='Kaydet' onPress={() => { onSubmit({ weddingCode: weddingC, accountTl: item.tlText, accountEuro: item.euroText, accountUsd: item.dollarText, accountHolderType: item.accountHolderType }) }} /> </View> )} </View> ); }) : ( <View style={{ alignItems: 'center', paddingVertical: 40 }}> <Text>Yükleniyor...</Text> </View> )} </ScrollView>
额外注意点
- 原代码中渲染时误用了
Data.map,需改为状态变量名Data1.map。 - 列表项必须添加唯一
key属性,避免React渲染警告。 - 在数据生成函数中添加了空值兜底(
|| ''),避免姓名显示为undefined undefined。
内容的提问来源于stack exchange,提问作者Alperen Kapusuz
相关产品推荐
相关产品推荐

