【问题标题】:How to delete from Firebase with React?如何使用 React 从 Firebase 中删除?
【发布时间】:2021-05-04 14:17:11
【问题描述】:

我正在尝试向帖子添加删除按钮,以便我可以从频道中删除单个帖子。我使用 Firebase 作为我的数据库,并且帖子集合嵌套在频道集合中。我为每个帖子添加了一个按钮,创建了一个名为 handleDel 的 onClick 事件,我尝试在频道集合中找到帖子并将其删除,但我无法删除我的帖子。

const db = firebaseApp.firestore()

Post.js

function Post({ user, post, timestamp }) {
    const channelId = useSelector(selectChannelId)


    const handleDel = () => {
        db.collection('channels')
        .doc(channelId)
        .collection('posts')
        .doc(post).delete().then(() => {
            console.log("Document successfully deleted!");
        }).catch((error) => {
            console.error("Error removing document: ", error);
        });
    }


    return (
        <div className='post'>
            <Avatar src={user.photo}
            />
            <div className="post__content">
                <h4>{user.displayName}
                    <span className='post__timestamp'>
                        <ClearIcon 
                            className='clearIcon'
                            onClick={handleDel}
                            id={post.id}
                            />
                        {new Date(timestamp?.toDate()).toUTCString()}
                    </span>
                </h4>
                <p className='post__text'>
                    {post}
                </p>
            </div>
        </div>
    )
}

Posts.js 了解更多上下文

function Posts() {
    const user = useSelector(selectUser)
    const channelId = useSelector(selectChannelId)
    const channelName = useSelector(selectChannelName)

    const [input, setInput] = useState('')
    const [posts, setPosts] = useState([])

    useEffect(() => {
        if (channelId) {
            db.collection('channels')
                .doc(channelId)
                .collection('posts')
                .orderBy('timestamp', 'asc')
                .onSnapshot((snapshot) =>
                    setPosts(snapshot.docs.map(doc => ({...doc.data(), id: doc.id})))
            )
        }
        }, [channelId])

    const sendPost = e => {
        e.preventDefault()

        db.collection('channels')
            .doc(channelId)
            .collection('posts')
            .add({
                timestamp: firebase.firestore.FieldValue.serverTimestamp(),
                post: input,
                user: user,
            })
            setInput('')
        }

    return (
        <div className='posts__container'>
            <ChannelTitle channelName={channelName} />
                <div className="posts">
                    {posts.map((post) => (
                    <Post
                        timestamp={post.timestamp}
                        post={post.post}
                        user={post.user}
                        id={post.id}
                        key={post.id}
                    />
                    ))}
                </div>
            <div className="post__input">
                <AddCircleIcon />
                <form>
                    <input 
                        type="text" 
                        placeholder={`Post to #${channelName}`}
                        value={input}
                        disabled={!channelId}
                        onChange={e => setInput(e.target.value)}/>
                    <button 
                        type='submit'
                        className='post__inputButton'
                        onClick={sendPost}>
                        Send</button>
                </form>
                <div className="post__inputIcons">
                    <GifIcon />
                    <EmojiEmotionsIcon />
                </div>
            </div>
        </div>
    )
}

我也试过

    const handleDel = () => {
        db.collection('posts')
        .doc(post).delete().then(() => {
            console.log("Document successfully deleted!");
        }).catch((error) => {
            console.error("Error removing document: ", error);
        });
    }

    const handleDel = () => {
        db.collection('channels')
        .doc(channelId)
        .collection('posts')
        .doc(post.id).delete().then(() => {
            console.log("Document successfully deleted!");
        }).catch((error) => {
            console.error("Error removing document: ", error);
        });
    }

我的控制台显示“文档已成功删除!”但该帖子仍在数据库中并且仍然显示。任何见解将不胜感激。

【问题讨论】:

    标签: reactjs firebase redux react-redux


    【解决方案1】:

    看看这些行:

    (<Post
        timestamp={post.timestamp}
        post={post.post}
        user={post.user}
        id={post.id}
        key={post.id}
    />)
    
    function Post({ user, post, timestamp }) {
    

    在这里,您将属性idposttimestampuser 传递到您的组件中,但只拉出posttimestampuser。另外,这里的post不是post对象(里面有idtimestamp等)而是帖子的文本内容,原来是input在发帖时的值,作为细绳。这意味着您的Post 组件不知道它自己的ID,因为post.id 在这种情况下是undefined。另外,因为您正在使用.doc(post) 删除文档,所以删除操作会成功,因为您最终会删除一个以您的消息内容命名的文档,例如/channels/${channelId}/posts/"This is my message!",而不是您要删除的内容,即@987654340 @。

    要更正此问题,您可以将其更改为:

    function Post({ id: postId, user, post, timestamp }) {
      const channelId = useSelector(selectChannelId)
    
      const handleDel = () => {
        return db.collection('channels') // note return of promise chain
          .doc(channelId)
          .collection('posts')
          .doc(postId)
          .delete()
          .then(
            () => {
              console.log("Document successfully deleted!");
            },
            (error) => {
              console.error("Error removing document: ", error);
            }
          );
      }
    
      /* ... rest of component ... */
    }
    

    其他注意事项:

    • 将文档的 post 字段重命名为 content 或类似名称,以消除整个帖子与其内容之间的歧义
    • 使用postData 而不是仅仅使用postpostDataList/postDataArray 而不是仅仅使用posts 来消除它们的歧义或使用TypeScript 来帮助捕捉这些错别字
    • 对于每个帖子,您都调用useSelector 以获取channelId。这很好,但由于这里有明确的父子关系,您可以将channelId 与来自Posts 组件的帖子数据一起传递以提高性能。
    • 频道侦听器 (useEffect(/* ... */, [channelId])) 不会自行清理
    • 频道中的帖子没有分页。 (想象一个包含数百条消息的一个月前的对话链,其中至少有 10 个用户在收听该频道 - 所有这些用户是否都需要一次所有这些消息? - 这是 1000 多个文档读取,而每个用户可能只需要 10 个)
    • sendPost 点击处理程序在清除输入之前不会等待确认消息已发送
    • channelId 为假时,sendPost 点击处理程序不会显示错误
    • sendPost 点击处理程序不会在未能将消息添加到数据库时显示错误
    • sendPost 点击处理程序允许发布空消息
    • channelId 为假时,发送按钮不会被禁用
    • user 的值没有经过错误检查,也不清楚这是 User 对象、它们的名称还是它们的 UID。

    【讨论】:

      【解决方案2】:

      试试这个。

      您需要在 API 调用中传递帖子/列表的唯一 ID 以删除特定的数据库条目

      改进

      <ClearIcon 
          className='clearIcon'
          onClick={() => handleDel(post.id)}
          id={post.id}
       />
      

      功能

      const handleDel = (id) => {
              db.collection('channels')
              .doc(channelId)
              .collection('posts')
              .doc(id).delete().then(() => {
                  console.log("Document successfully deleted!");
              }).catch((error) => {
                  console.error("Error removing document: ", error);
              });
          }
      

      【讨论】:

        猜你喜欢
        • 2021-11-05
        • 2015-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多