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

React Native Expo安卓应用点击发布按钮时崩溃求助

React Native Expo应用添加帖子时崩溃的修复方案

问题根源分析

你的FeedScreen中触发崩溃的核心问题有以下几点:

  1. Firestore时间戳API引用错误
    代码中直接使用firestore.FieldValue.serverTimestamp(),但未正确关联已导入的firebase实例,导致变量未定义报错。

  2. Keyboard组件未导入
    调用Keyboard.dismiss()但未从react-native导入Keyboard模块,引发未定义错误。

  3. 未处理用户未登录的边界情况
    若用户未登录,auth?.currentUser为null,此时存入Firebase的id和author会是undefined,可能触发数据写入异常。

  4. useLayoutEffect依赖缺失
    useLayoutEffect中使用了navigation但未加入依赖数组,可能导致导航配置异常。

修复后的FeedScreen代码

import React, { useState, useEffect, useLayoutEffect } from 'react';
import * as firebase from 'firebase';
import { View, Text, FlatList, StyleSheet, Modal, Keyboard } from 'react-native'; // 新增Keyboard导入
import { TouchableOpacity } from 'react-native-gesture-handler';
import { auth, db } from '../firebase';
import { AntDesign, Ionicons } from '@expo/vector-icons';
import { Input, Button, Avatar } from 'react-native-elements';

const FeedScreen = ({ navigation }) => {
  const [posts, setPosts] = useState([]);
  const [addpost, setAdd] = useState(false);
  const [postText, setPostText] = useState('');
  const likes = 0;

  useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <TouchableOpacity>
          <AntDesign
            onPress={() => setAdd(true)}
            name="pluscircleo"
            size={27}
            color="black"
          />
        </TouchableOpacity>
      ),
    });
  }, [navigation]); // 新增navigation依赖

  useEffect(() => {
    const unsubscribe = db
      .collection('posts')
      .orderBy('createdAt', 'desc')
      .onSnapshot((querySnapshot) => {
        const newPosts = [];
        querySnapshot.forEach((doc) => {
          newPosts.push({
            id: doc.data().id,
            createdAt: doc.data().createdAt,
            text: doc.data().text,
            author: doc.data().author,
          });
        });
        setPosts(newPosts);
      });
    return unsubscribe; // 新增清理函数,防止内存泄漏
  }, []);

  const onAddButtonPress = () => {
    // 先判断用户是否登录
    if (!auth.currentUser) {
      alert('请先登录');
      return;
    }
    // 修正Firestore时间戳引用
    const timestamp = firebase.firestore.FieldValue.serverTimestamp();
    setAdd(false);
    const data = {
      createdAt: timestamp,
      text: postText,
      id: auth.currentUser.email,
      author: auth.currentUser.displayName || '匿名用户', // 处理displayName为空的情况
    };
    db
      .collection('posts')
      .add(data)
      .then((_doc) => {
        setPostText('');
        Keyboard.dismiss();
      })
      .catch(err => {
        console.error('添加帖子失败:', err); // 新增错误捕获,方便排查
        alert('添加帖子失败,请重试');
      });
  };

  const postItem = ({ item, index }) => {
    // 处理author为空的情况,避免substr报错
    const displayAuthor = item.author || '匿名用户';
    return (
      <View style={styles.postview}>
        <View
          style={{
            borderBottomWidth: 2,
            borderBottomColor: '#E2E2E2',
            flex: 1,
            flexDirection: 'row',
          }}>
          <Avatar
            size={40}
            rounded
            title={displayAuthor.substr(0, 1)}
            containerStyle={{ backgroundColor: '#6733b9' }}
          />
          <Text style={styles.autor}>{displayAuthor}</Text>
        </View>
        <View>
          <Text style={styles.txt}>{item.text}</Text>
        </View>
      </View>
    );
  };

  return (
    <View style={{flex:1}}> {/* 新增flex:1,避免FlatList无法占满屏幕 */}
      <Modal visible={addpost} animationType="slide"> {/* 新增动画类型,提升体验 */}
        <View style={{padding:20, marginTop:40}}>
          <Ionicons name="close" size={40} onPress={() => setAdd(false)} />
          <Text style={styles.txt2}>Add Post</Text>
          <View style={styles.form}>
            <Input
              placeholder="Enter post text"
              value={postText}
              onChangeText={(text) => setPostText(text)}
            />
            <Button title="Add" onPress={onAddButtonPress} />
          </View>
        </View>
      </Modal>
      <FlatList
        data={posts}
        renderItem={postItem}
        keyExtractor={(item) => item.id}
        style={{backgroundColor:'#E5E7E6'}} // 匹配App.js的背景色
      />
    </View>
  );
};

const styles = StyleSheet.create({
  postview: {
    marginBottom: 10,
    paddingVertical: 15, // 替换'auto',因为paddingVertical不支持auto值
    paddingHorizontal:10,
    backgroundColor: 'white',
    borderRadius: 30,
  },
  autor: {
    fontSize: 18,
    marginLeft:10,
    marginTop: 7,
  },
  txt: {
    marginTop: 20,
    fontSize: 17,
    marginHorizontal: 20,
    marginBottom: 20,
  },
  txt2: {
    marginHorizontal: 'auto',
    fontSize: 40,
    marginTop: 20,
  },
  form: {
    paddingTop: 40, // 减少padding,避免输入框太靠下
  },
});

export default FeedScreen;

额外修复点说明

  • 新增了useEffect的清理函数,取消Firestore快照监听,防止内存泄漏
  • 处理了author为空的情况,避免substr(0,1)报错
  • 修正了paddingVertical: 'auto'的错误,React Native的padding不支持auto值
  • 新增了错误捕获和提示,方便排查添加帖子失败的原因
  • 给Modal添加了动画类型,提升用户体验

内容的提问来源于stack exchange,提问作者EmikDEV

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 00:05:26