React Native使用Hooks解析XML存入数组时遇对象未定义错误
问题排查:React Hooks解析XML时出现
undefined is not an object错误 我尝试用React Hooks获取XML数据并存入meterDataList数组,但控制台抛出以下错误:
undefined is not an object (evaluating 'result['counter']['counternumber']')
我的代码实现:
function getReadingOrder(Emp_Number,{navigation}){ const [meterDataList,setArray] = useState([]); fetch('http://localhost/gecol/partner/api.php?emp_number='+`${Emp_Number}`, { method: 'POST', headers: { Accept: 'text/plain', 'Content-Type': 'text/plain' } }) .then((response) => response.text()) .then((data) => { var xml2js = require('xml2js'); var parser = new xml2js.Parser(); parser.parseString(data, function(err,result){ // meterDataList.push([{servicePoint:222, counternumber:result['counter']['counternumber']}]) setArray(meterDataList => [meterDataList,{servicePoint:222, counternumber:result['counter']['counternumber']}]) }) }) const [expanded, setExpanded] = React.useState(true); console.log(meterDataList); return ( <SafeAreaProvider > <View style={ReaderHome.Accordion}> {meterDataList.map((meter, i) => ( <ListItem.Accordion content={ <> <Avatar size={64} icon={{ name: 'home', type: 'AntDesign' }} containerStyle={{ backgroundColor: '#1f95c0' }}/> <ListItem.Content> <ListItem.Title style={{left:10}}><Text style={ReaderHome.ConsumerName}>{meter.consumer}</Text></ListItem.Title> <ListItem.Subtitle style={{left:10}}><Text style={ReaderHome.ServiceNumber}>{meter.servicePoint}</Text></ListItem.Subtitle> </ListItem.Content> </> } isExpanded={expanded} onPress={() => { setExpanded(!expanded); }} > <ListItem key={i} onPress={alert(meter.lastdate)} bottomDivider> <Avatar title={''} source={''} /> <ListItem.Content> <ListItem.Title>{meter.currentread}</ListItem.Title> <ListItem.Subtitle>meter.lastread</ListItem.Subtitle> </ListItem.Content> <ListItem.Chevron /> </ListItem> </ListItem.Accordion>))} </View> </SafeAreaProvider>); }
错误原因及修复方案
1. 核心问题:解析后的XML结构不符合预期
报错说明result['counter']或者result['counter']['counternumber']是undefined,大概率是xml2js解析后的结构和你预想的不一样——xml2js默认会把所有节点(哪怕只有一个)转成数组,比如你的XML如果是:
<root> <counter> <counternumber>12345</counternumber> </counter> </root>
解析后可能是result.root.counter[0].counternumber[0],而非你直接访问的result['counter']['counternumber']。
2. 分步修复
第一步:先确认解析后的实际结构
在解析回调里打印错误和结果,搞清楚真实的结构:
parser.parseString(data, function(err, result){ console.log('解析错误:', err); console.log('解析结果:', result); // 看控制台输出的结构再调整访问方式 })
第二步:调整xml2js解析配置(可选)
如果不想处理数组结构,可以创建Parser时关闭自动数组转换:
var parser = new xml2js.Parser({ explicitArray: false });
⚠️ 注意:如果XML里有多个同名<counter>节点,这个配置会只保留最后一个,需根据实际XML结构选择。
第三步:添加安全访问判断
不管结构如何,先做空值校验避免报错:
parser.parseString(data, function(err, result){ if (err) { console.error('XML解析失败:', err); return; } // 安全访问字段,可选链式操作符(ES2020+)或逻辑与 const counterNumber = result?.counter?.counternumber; // 兼容老版本JS:const counterNumber = result && result.counter && result.counter.counternumber; if (counterNumber) { // 修正setArray的写法:用扩展运算符展开原数组,而非嵌套 setArray(prev => [...prev, { servicePoint:222, counternumber: counterNumber }]); } else { console.log('未找到counternumber字段,解析结果:', result); } })
第四步:修复其他代码问题
- Hook位置错误:
useState必须放在组件最顶部,把const [expanded, setExpanded]移到const [meterDataList,setArray]下面 - 重复引入模块:
var xml2js = require('xml2js');移到组件外部,不要在then回调里重复引入 - alert触发时机错误:
onPress={alert(meter.lastdate)}会在渲染时直接执行alert,改成onPress={() => alert(meter.lastdate)} - 字符串插值错误:
ListItem.Subtitle里的meter.lastread是字符串,改成{meter.lastread}
内容的提问来源于stack exchange,提问作者MrObscure
相关产品推荐
相关产品推荐

