React Native从数组取数在ScrollView中无法显示的问题排查
问题解决:异步获取数据后ScrollView不渲染内容
核心原因
你直接修改普通JavaScript对象data,React无法监听这种手动修改的变化,所以即使异步函数里数据已经填充完成,组件也不会触发重新渲染,导致ScrollView里看不到内容。
修复步骤
- 用React状态管理数据:把
data改成useState状态变量,状态更新时React会自动触发组件重渲染。 - 用useEffect执行异步逻辑:把获取数据的异步函数放到
useEffect中,确保组件挂载后只执行一次,避免重复请求。 - 完善TypeScript类型:去掉
@ts-ignore,定义清晰的类型,避免类型报错。
完整修复代码示例
1. 定义TypeScript类型
// 定义文档类型常量 const MEDICAL = 'Medical'; const INSTITUTIONAL = 'Institutional'; const OTHER = 'Other'; // 定义单个文档的类型 type DocumentItem = { documentType: typeof MEDICAL | typeof INSTITUTIONAL | typeof OTHER; notice: string; file: string; }; // 定义数据对象的类型 type DataObject = { [MEDICAL]: DocumentItem[]; [INSTITUTIONAL]: DocumentItem[]; [OTHER]: DocumentItem[]; };
2. 组件内状态与数据获取逻辑
import { useState, useEffect } from 'react'; // 导入你的etherContract、NativeBase组件等 const YourComponent = () => { // 初始化状态 const [data, setData] = useState<DataObject>({ [MEDICAL]: [], [INSTITUTIONAL]: [], [OTHER]: [] }); const keys = Object.keys(data) as Array<keyof DataObject>; useEffect(() => { const fetchData = async () => { try { const personalInfo = await etherContract.getMyInfo(); // 初始化新的空数据对象,避免直接修改原状态 const newData: DataObject = { [MEDICAL]: [], [INSTITUTIONAL]: [], [OTHER]: [] }; personalInfo.forEach(info => { const parsedInfo: DocumentItem = JSON.parse(info); switch(parsedInfo.documentType) { case MEDICAL: newData[MEDICAL].push(parsedInfo); break; case INSTITUTIONAL: newData[INSTITUTIONAL].push(parsedInfo); break; case OTHER: newData[OTHER].push(parsedInfo); break; default: break; } }); // 更新状态,触发组件重渲染 setData(newData); } catch (e) { console.error('获取数据失败:', e); } }; fetchData(); }, []); // 空依赖数组确保只执行一次 // 渲染部分 return ( <ScrollView> {keys.map((item, idx) => ( data[item].length > 0 ? ( <View key={idx}> <Center> <Heading>{item}</Heading> {data[item].map((subItem, key) => ( <View key={key}> <Box alignItems="center"> <Box rounded="lg" overflow="hidden" borderColor="coolGray.200" borderWidth="1" _dark={{ borderColor: "coolGray.600", backgroundColor: "gray.700" }} _web={{ shadow: 2, borderWidth: 0 }} _light={{ backgroundColor: "gray.50" }} > <Stack p="4" space={3}> <Stack space={2}> <Center> <Link href={subItem.file}> <Icon as={AntDesign} name="eyeo" size="10" color={"red.400"} /> </Link> </Center> </Stack> <Text fontWeight="400"> {subItem.notice} </Text> </Stack> </Box> </Box> </View> ))} </Center> </View> ) : ( <View key={idx}></View> ) ))} </ScrollView> ); }; export default YourComponent;
关键说明
- 状态更新必须用setData:不能直接修改
data对象,必须通过setState方法更新,React才能检测到变化并重新渲染。 - useEffect的空依赖数组:确保数据获取逻辑只在组件挂载时执行一次,避免重复请求。
- 类型定义:清晰的类型可以避免TypeScript报错,同时让代码更易维护。
内容的提问来源于stack exchange,提问作者DlukikPython
相关产品推荐
相关产品推荐

