React Native中DataTable数据拉取填充及报错问题排查
问题背景
在React Native项目中实现接口数据拉取、填充至react-native-paper的DataTable组件功能时,运行触发如下警告:
Warning: Functions are not valid as a React child. This may happen if you return a Component instead of
from render. Or maybe you meant to call this function rather than return it.return (<Component/>)
该警告含义为函数无法作为合法的React子元素渲染,常见触发场景为render方法中返回了组件类本身而非<Component/>形式的JSX元素,或是直接返回了未调用的函数。
原业务代码如下:
import React, { useState,useEffect } from 'react'; import { StyleSheet, SafeAreaView, ScrollView,Text, View, Modal } from 'react-native'; import { DataTable } from 'react-native-paper'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack'; import COLORS from '../src/conts/colors'; import Button from '../src/views/components/Button'; const List = ({navigation}) => { const [data,setData] = useState([]) const [loading,setLoading]= useState(true) const fetchData = ()=>{ fetch("https://flow.simpas.ai/hortus/paysagiste/category?businessid=0899607494") .then(res=>res.json()) .then(results=>{ setData(results) setLoading(false) }) } useEffect(()=>{ fetchData() },[]) const renderList = ((item)=>{ return( <DataTable.Row style={styles.tableRow} key={item.businessid}> <DataTable.Cell textStyle={{color: '#777777',fontFamily: 'Roboto'}} onPress={() => navigation.navigate("Edit",{item})} >{item.title}</DataTable.Cell> <DataTable.Cell textStyle={{color: '#FEB296', fontFamily: 'Roboto'}}>{item.title}</DataTable.Cell> <DataTable.Cell textStyle={{color: '#777777', fontFamily: 'Roboto'}}>{item.price}</DataTable.Cell> </DataTable.Row> ) }) return ( <SafeAreaView style={{ flex: 1}}> <ScrollView contentContainerStyle={{paddingTop: 50, paddingHorizontal: 20}}> <Text style={{color: COLORS.black, fontSize: 40, fontWeight: 'bold', fontFamily: 'Roboto',textAlign: 'center'}}> List of Companies </Text> <Text style={{color: COLORS.grey, fontSize: 18, marginVertical: 10, fontFamily: 'Roboto', textAlign: 'center'}}> Check Our Companies Details </Text> <DataTable style={styles.container} > <DataTable.Header style={styles.tableHeader} > <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>BusinessId</DataTable.Title> <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>Title</DataTable.Title> <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>Price</DataTable.Title> </DataTable.Header> </DataTable> {renderList} </ScrollView> </SafeAreaView> ); }; export default List; const styles = StyleSheet.create({ container: { padding: 0, }, tableHeader: { backgroundColor: '#50E3C2', }, tableRow: { backgroundColor: '#fff', }, });
运行报错截图:
问题根因
代码存在2个直接触发问题的错误,另有1个逻辑遗漏:
- 直接将
renderList函数本身放在JSX中渲染,没有遍历接口返回的data数组调用该渲染函数,完全匹配警告中「返回未调用函数作为React子元素」的触发条件 DataTable组件在Header节点后就提前闭合,后续就算正确渲染表格行,行内容也不会被包裹在表格组件内部- 定义了
loading加载状态但未使用,接口请求没有异常捕获逻辑,请求失败时会一直卡在加载状态
修复后代码
import React, { useState,useEffect } from 'react'; import { StyleSheet, SafeAreaView, ScrollView,Text, ActivityIndicator } from 'react-native'; import { DataTable } from 'react-native-paper'; import COLORS from '../src/conts/colors'; import Button from '../src/views/components/Button'; const List = ({navigation}) => { const [data,setData] = useState([]) const [loading,setLoading]= useState(true) const fetchData = ()=>{ fetch("https://flow.simpas.ai/hortus/paysagiste/category?businessid=0899607494") .then(res=>res.json()) .then(results=>{ setData(results) setLoading(false) }) .catch(err => { console.log('接口请求失败:', err) setLoading(false) }) } useEffect(()=>{ fetchData() },[]) const renderList = ((item)=>{ return( <DataTable.Row style={styles.tableRow} key={item.businessid}> <DataTable.Cell textStyle={{color: '#777777',fontFamily: 'Roboto'}} onPress={() => navigation.navigate("Edit",{item})} >{item.businessid}</DataTable.Cell> <DataTable.Cell textStyle={{color: '#FEB296', fontFamily: 'Roboto'}}>{item.title}</DataTable.Cell> <DataTable.Cell textStyle={{color: '#777777', fontFamily: 'Roboto'}}>{item.price}</DataTable.Cell> </DataTable.Row> ) }) return ( <SafeAreaView style={{ flex: 1}}> <ScrollView contentContainerStyle={{paddingTop: 50, paddingHorizontal: 20}}> <Text style={{color: COLORS.black, fontSize: 40, fontWeight: 'bold', fontFamily: 'Roboto',textAlign: 'center'}}> List of Companies </Text> <Text style={{color: COLORS.grey, fontSize: 18, marginVertical: 10, fontFamily: 'Roboto', textAlign: 'center'}}> Check Our Companies Details </Text> { loading ? <ActivityIndicator size="large" color="#50E3C2" style={{marginVertical: 30}}/> : <DataTable style={styles.container}> <DataTable.Header style={styles.tableHeader}> <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>BusinessId</DataTable.Title> <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>Title</DataTable.Title> <DataTable.Title textStyle={{color: '#fff',fontSize: 16, fontFamily: 'Roboto'}}>Price</DataTable.Title> </DataTable.Header> {data.map(renderList)} </DataTable> } </ScrollView> </SafeAreaView> ); }; export default List; const styles = StyleSheet.create({ container: { padding: 0, }, tableHeader: { backgroundColor: '#50E3C2', }, tableRow: { backgroundColor: '#fff', }, });
修复点说明
- 移除了未使用的
NavigationContainer、createNativeStackNavigator、Modal等无效导入,减少不必要的资源占用 - 替换原代码直接渲染
{renderList}的错误写法为{data.map(renderList)},遍历接口返回的数据集生成表格行,从根源解决函数作为子元素渲染的警告 - 调整
DataTable标签闭合位置,将所有表格行节点放在DataTable组件内部,保证表格结构符合组件要求 - 补全loading状态渲染逻辑:接口请求过程中显示加载指示器,请求完成后再渲染表格内容
- 给fetch请求增加catch异常捕获,避免请求失败时页面一直停留在加载状态
- 修正第一列表格单元格的渲染错误:原代码第一列渲染内容为
item.title,和表头BusinessId不匹配,改为渲染item.businessid字段
内容的提问来源于stack exchange,提问作者HASSANE BOUKHAL
相关产品推荐
相关产品推荐

