useState 数组未定义,即使它被初始化为空数组

useState array is undefined even though it is initialized as empty array

我正在使用 Firebase v9 在 React Native Expo 项目中工作,但由于我的状态变量类别而出现错误(我认为这就是问题所在)。 此组件允许用户将类别添加到平面列表,如下所示:

如图所示,我已经收到一条警告:'[未处理的承诺拒绝:FirebaseError:使用无效数据调用函数 setDoc()。不支持的字段值:未定义(在文档 users/Hk4k6fKrtZZG1BGffFrOTRvuT2h2 的字段类别中找到)]'

当我添加类别时出现错误 -> 渲染错误:未定义不是对象(评估 'iter[symbol.iterator]')

这是我的 CategoryComponent 的代码:

import { StyleSheet, View, FlatList, Alert, Animated} from 'react-native'
import React, { useState, useEffect} from 'react'
import { db, } from '../../firebase/firebase'
import { doc, setDoc, onSnapshot} from 'firebase/firestore';
import firebase from 'firebase/compat/app';
import { Button, Divider, Subheading, Text, Modal, Portal, TextInput } from 'react-native-paper';
import Swipeable from 'react-native-gesture-handler/Swipeable'
import { TouchableOpacity } from 'react-native-gesture-handler';
import { useNavigation } from '@react-navigation/native';


export default function CategoryComponent() {
  const containerStyle = {backgroundColor: 'white', padding: 100, margin: 10};
  const [textInput, setTextInput] = useState('');
  const [visible, setVisible] = useState(false);
  const [categories, setCategories] = useState([])
  const navigation = useNavigation();
  const [dataFetch, setDataFetch] = useState(false);


  useEffect(
    () => 
      onSnapshot(doc(db, "users", `${firebase.auth().currentUser.uid}`), (doc) => {
        setCategories(doc.data().categories)
        setDataFetch(true)
      }
      ),
      console.log(categories),
    []
  );


  useEffect(() => {
    addToFirebase();
  }, [categories])


  const showModal = () => {
    setVisible(true);
  }
  

  const hideModal = () => {
    setVisible(false);
  }


  const categoryNavigate = (item) => {
    navigation.navigate("Your Organizer tasks", {item});
  }


  const addCategory = (textInput) => {
    setCategories((prevState) => {
      return [
        {name: textInput, id: Math.floor(Math.random() * 10000) + 1 },
        ...prevState
      ];
    })

    hideModal();
  }


  const addToFirebase = async() => {
    if(dataFetch) {
      await setDoc(doc(db, "users", `${firebase.auth().currentUser.uid}`), {
        categories: categories
      }, {merge: true});
    }
  };

  
  const deleteItem = (item) => {
    setCategories((prevState) => {
      return prevState.filter(category => category.id != item.id)
    })        
  }


  const DataComponent = (item) => {
    const rightSwipe = (progress, dragX) => {
      const scale = dragX.interpolate({
        inputRange: [-100, 0],
        outputRange: [1, 0],
        extrapolate: 'clamp'
      });

      return(
        <TouchableOpacity activeOpacity={0.8} onPress={() => deleteItem(item)}>
          <View>
            <Animated.Text style={[styles.deleteItem, {transform: [{scale}]}]}>Delete</Animated.Text>
          </View>
        </TouchableOpacity>
      )
    }

    return (
    <TouchableOpacity onPress={() => categoryNavigate(item)}>
      <Swipeable renderRightActions={rightSwipe}>
        <View>
          <Text>{item.name}</Text>
        </View>
      </Swipeable>
    </TouchableOpacity>
    )
  }


  return (
    <View>
      <Subheading>Your categories</Subheading>
        <View>
          <FlatList
          style={styles.flatList}
          keyExtractor={(item) => item.id}
          data={categories}
          renderItem={ ({item}) => (
            <DataComponent {...item}/>
            )}
            />
        </View>

      <View>
        <Button mode="contained" uppercase={false} onPress={showModal}>
          Add a category
        </Button>
      </View>
      <Portal>
        <Modal visible={visible} onDismiss={hideModal} contentContainerStyle={containerStyle}>
          <Text>Name your category: </Text>
          <TextInput placeholder="Enter category name" value={textInput} onChangeText={val => setTextInput(val)}/>
          <Button mode="contained" uppercase={false} onPress={() => addCategory(textInput)}>
            Add
          </Button>
        </Modal>
      </Portal>
    </View>
  )
}

我的 useEffect 中有 consol.logged 状态变量类别,我不明白为什么当我将它初始化为空数组时它显示“'undefined'”,所以我希望当平面列表中没有类别时,在状态变量类别的 consol.log 中看到一个空数组。

如果你清楚地看到对象中没有这样的类别类型键值,那么当你执行 setCategories(doc.data().categories) 它设置 categories 值未定义 .您不能合并或添加字段值未定义的文档。