You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

问题根源

  1. 初始状态类型错误:todo的初始值被设为对象{},但实际存储的是任务数组,FlatList要求data为数组类型。当用对象作为FlatList的数据源时,内部遍历会把对象的属性值当作React子元素渲染,而这些属性值是{text, dis}对象,React无法直接渲染对象,触发报错。
  2. 空数据处理缺失:首次打开应用时,AsyncStorage中无数据,JSON.parse会返回null,后续调用map或filter方法会报错。
  3. 状态修改不规范:删除任务时直接引用原状态数组,未创建副本,可能导致状态更新异常。

解决方案

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:15:36