React Native出现Objects are not valid as a React child错误,求解决
React Native任务管理应用报错排查:Objects are not valid as a React child
问题描述
开发React Native任务管理应用时遇到报错:
Objects are not valid as a React child: Found object with keys {mytext, mydis}

相关代码
import { View, Text, TextInput, Button, FlatList, ScrollView, TouchableOpacity, StyleSheet } from 'react-native' import React, { useEffect, useState } from 'react' import AsyncStorage from '@react-native-async-storage/async-storage' let todos = []; const MainScreen = () => { const [text, setText] = useState('') const [dis, setDis] = useState('') const [todo, setTodo] = useState({}) //Use Effect Call Get Data useEffect(() => { getTask() }, []) // Get Data const getTask = async () => { try { const todoss = await AsyncStorage.getItem('todo'); console.log(JSON.parse(todoss)) if (todoss !== null) { setTodo(JSON.parse(todoss)); } } catch (e) { alert('Get Data ' ) } } // Delete Task const clerText = async (index) => { const tempdata = todo; const selectedData = tempdata.filter((item, ind) => { return ind != index; }); setTodo(selectedData) await AsyncStorage.setItem('todo', JSON.stringify(selectedData)); }; // Set Data const saveTask = async () => { try { let temptodo = []; todos = []; let x = JSON.parse(await AsyncStorage.getItem('todo')); temptodo = x; temptodo.map(item => { todos.push(item); }); todos.push({ text: text, dis: dis }); await AsyncStorage.setItem('todo', JSON.stringify(todos)); } catch (e) { alert('Save Task ' + e) } } return ( <View> <Text>Name</Text> <TextInput value={text} onChangeText={setText} style={{ borderColor: '#000', borderWidth: 2, margin: 15, padding: 5 }} placeholder='Enter Task' /> <TextInput value={dis} onChangeText={setDis} style={{ borderColor: '#000', borderWidth: 2, margin: 15, padding: 5 }} placeholder='Enter Task' /> <Button title='Save Task' onPress={saveTask} /> {/* {todo.map((val)=> <Text>{val}</Text>)} */} <Button title='Delete Task' /> <FlatList data={todo} renderItem={({ item, index }) => ( <View style={styles.taskView} > <Text style={styles.taskText} > {item.text} </Text> <Text style={styles.taskDis} > {item.dis} </Text> <TouchableOpacity style={styles.taskBtn} onPress={() => clerText(index)} > <Text style={styles.taskBtnText} > ❌ </Text> </TouchableOpacity> </View> )} /> {/* <Text>{text}</Text> <Text>{todo}</Text> */} </View> ) } const styles = StyleSheet.create({ taskView: { flex: 1, alignItems: 'center', margin: 30, borderRadius: 5, padding: 10, backgroundColor: '#f5f5f5' }, taskText: { fontWeight: 'bold', textTransform: 'uppercase', fontSize: 20, textAlign: 'left', alignSelf: 'flex-start', marginVertical: 5, marginLeft: 15, }, taskDis: { textTransform: 'capitalize', color: '#050505', }, taskBtn: { alignSelf: 'flex-end', marginVertical: 5 }, taskBtnText: { } }) export default MainScreen
问题根源
- 初始状态类型错误:
todo的初始值被设为对象{},但实际存储的是任务数组,FlatList要求data为数组类型。当用对象作为FlatList的数据源时,内部遍历会把对象的属性值当作React子元素渲染,而这些属性值是{text, dis}对象,React无法直接渲染对象,触发报错。 - 空数据处理缺失:首次打开应用时,AsyncStorage中无数据,
JSON.parse会返回null,后续调用map或filter方法会报错。 - 状态修改不规范:删除任务时直接引用原状态数组,未创建副本,可能导致状态更新异常。
解决方案
1. 修正初始状态
将todo的初始值改为空数组:
const [todo, setTodo] = useState([])
2. 修复数据获取逻辑
处理AsyncStorage返回null的情况:
const getTask = async () => { try { const todoss = await AsyncStorage.getItem('todo'); if (todoss !== null) { setTodo(JSON.parse(todoss)); } else { setTodo([]); // 首次打开时初始化空数组 } } catch (e) { alert('获取数据失败: ' + e) } }
3. 简化并优化保存任务逻辑
直接处理空数据情况,避免冗余代码:
const saveTask = async () => { try { // 获取现有数据,若无则为空数组 const existingTodos = JSON.parse(await AsyncStorage.getItem('todo')) || []; // 添加新任务并创建新数组 const newTodos = [...existingTodos, { text: text, dis: dis }]; // 保存并更新状态 await AsyncStorage.setItem('todo', JSON.stringify(newTodos)); setTodo(newTodos); // 清空输入框 setText(''); setDis(''); } catch (e) { alert('保存任务失败: ' + e) } }
4. 规范删除任务逻辑
创建数组副本,避免直接修改原状态:
const clerText = async (index) => { const selectedData = todo.filter((item, ind) => ind !== index); setTodo(selectedData); await AsyncStorage.setItem('todo', JSON.stringify(selectedData)); };
内容的提问来源于stack exchange,提问作者Gaurav Singh
相关产品推荐
相关产品推荐

