React Native中DataTable拉取数据及函数作为React子元素报错解决
问题描述
实现接口数据渲染到DataTable组件功能时,运行时报错:
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.
翻译:函数不能作为合法的React子元素。出现这个问题通常是因为render方法中直接返回了组件本身而非组件渲染结果,或者你本应调用函数却直接返回了函数定义。
问题代码
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', }, });
错误原因
代码存在5个核心问题:
- 直接将
renderList函数本身作为子元素渲染,没有执行函数遍历数据生成JSX节点,这是触发报错的直接原因 - DataTable.Row行组件被放在了DataTable闭合标签外部,不符合组件的结构要求,表格无法正常渲染
- 表头第一列定义为BusinessId,但对应单元格渲染的是title字段,字段映射错误
- 定义了loading状态但未使用,接口请求过程中无状态提示
- fetch请求未做错误捕获,接口请求失败时loading状态会一直卡住,也无法定位请求异常
- renderList定义时外层多包裹了一层括号,属于冗余写法,不影响运行但可以移除
修复方案
- 将
{renderList}修改为{data.map(renderList)},遍历接口返回的数组数据,调用renderList为每一条数据生成表格行 - 将遍历生成的表格行移动到DataTable组件内部,放在DataTable.Header标签之后
- 修正第一列单元格的字段,将
{item.title}改为{item.businessid},和表头对应 - 增加loading状态判断,请求过程中显示加载提示
- 给fetch请求增加catch错误捕获,请求失败时重置loading状态,打印错误日志方便排查
- 移除renderList定义外层多余的括号
修复后的完整代码:
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) }) .catch(err => { console.error('数据请求失败:', 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 ? <Text style={{textAlign: 'center', marginTop: 20, fontFamily: 'Roboto', color: COLORS.grey}}>数据加载中...</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> {data.map(renderList)} </DataTable> } </ScrollView> </SafeAreaView> ); }; export default List; const styles = StyleSheet.create({ container: { padding: 0, }, tableHeader: { backgroundColor: '#50E3C2', }, tableRow: { backgroundColor: '#fff', }, });
内容的提问来源于stack exchange,提问作者HASSANE BOUKHAL
相关产品推荐
相关产品推荐

