How to get id from clicked doc firebase react?

Viewed 133

I am trying to get the id from a doc when I click a delete button. so the user can delete the post. I got far enough to show the button if the user is the uploader. but, I don't know how to get the id from the clicked document. I tried this:

{auth.currentUser.uid === uploaderId ? (
        <div
          onClick={(e) => {
            if (auth.currentUser.uid === uploaderId) {
              e.stopPropagation();
            deleteDoc(doc(db, "posts", id));
            }
          }}
        >
          <div>
            <button>️</button>
          </div>
        </div>
      ) : (
        <div>
        </div>
      )}

but that doesn't work and gives me the error: Uncaught TypeError: Cannot read properties of undefined (reading 'indexOf') so to summarize how do I get the id from the document

full code:

import React, { useEffect, useRef, useState } from 'react';
import './App.css';

import { initializeApp } from "firebase/app";
import { getFirestore, collection, orderBy,
 query, Timestamp, addDoc, limitToLast,
 deleteDoc, doc, } from "firebase/firestore";
import { confirmPasswordReset, getAuth, GoogleAuthProvider, signInWithPopup,  } from "firebase/auth";

import { useAuthState } from "react-firebase-hooks/auth";
import { useCollectionData } from "react-firebase-hooks/firestore";


// Initialize Firebase
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);

function App() {
  const [user] = useAuthState(auth);
  return (
    <div className="App">
      <Header/>
      {/* <Picker/> */}
      <section>
      <SignOut/>
      {/* <ShowProfile/> */}
      <Upload/>
        {user ? <Feed /> : <SignIn />}
      </section>
    </div>
  );
}
function Header() {
  return (
      <h1 className='headerTxt'>SHED</h1>

  )
}
// function Picker() {
  
// }
function SignIn() {
  const signInWithGoogle = () =>{
    const provider = new GoogleAuthProvider();
    signInWithPopup(auth, provider)
  }
  return (
    <button className='SignIn' onClick={signInWithGoogle}>sign in with google</button>
  )
}
function SignOut() {
  return auth.currentUser && (

    <button onClick={() => auth.signOut()}>Sign out</button>
  )
}
function Feed() {

  const postsRef = collection(db, 'posts');
  const qwery = query(postsRef,orderBy('createdAt'), limitToLast(25), );
  
  const [posts] = useCollectionData(qwery, {idField: "id"});

  return (
    <>
    <main>
      {posts && posts.map(msg => <Post key={msg.id} post={msg} />)}
    </main>
    </>
  )
}
function Post(props) {

  const {text, photoURL, displayName, uid, uploaderId, id} = props.post;

  return (
    <div className={"post"}>
      <div className='msg'>
      <div className='top'>
      <img src={photoURL} alt="" />
      <sub>{displayName}</sub>
      </div>
      <hr />
      <p>{text}</p>
      {auth.currentUser.uid === uploaderId ? (
            <div
              onClick={(e) => {
                if (auth.currentUser.uid === uploaderId) {
                  e.stopPropagation();
                deleteDoc(doc(db, "posts", id));
                }
              }}
            >
              <div>
                <button>️</button>
              </div>
            </div>
          ) : (
            <div>
            </div>
          )}
        {/* <button>❤️</button> */}
      </div>
    </div>
  )
}
// function ShowProfile() {
//   return(
//     <div>
//       <button onClick={queryMine}>my posts</button>
//     </div>
//   )
// }
function Upload() {
  const postsRef = collection(db, 'posts');

  const [formValue, setFormValue] = useState('');
  const sendpost = async(e) =>{
    e.preventDefault();

    const {uid, photoURL, displayName} = auth.currentUser;

    if (formValue !== "" && formValue !== " ") {
      await addDoc(postsRef, {
        text: formValue,
        createdAt: Timestamp.now(),
        displayName,
        uploaderId: uid,
        photoURL
      })
      setFormValue('')
    }
  }

  return auth.currentUser &&(
    <form onSubmit={sendpost}>
    <textarea name="" id="" cols="30" rows="10"
    value={formValue} onChange={(e) => setFormValue(e.target.value)}
    ></textarea>
    <button type='submit'>➜</button>
  </form>
  )
}




export default App;```

1 Answers

Get the data (doc id and doc data) using querySnapshot and merge them into one object. Save an array of objects to a state and pass what you need as properties. For example:

...    
    const querySnapshot = await getDocs(collection(db, `users/${email}/todos`))
        const todos = []
        querySnapshot.forEach(doc => {
            todos.push({
                id: doc.id,
                text: doc.data().text,
                isCompleted: doc.data().isCompleted,
            })
        })
        return todos

Here is a simple example of the Todo App, but the logic is the same. In the Todo component, I get the doc id as props. Full code:

import { collection, getDocs } from 'firebase/firestore'
import { useEffect, useState } from 'react'
import { db } from '../../app/firebase'
import Todo from '../Todo'
import './style.css'

const TodoList = () => {

    const [todos, setTodos] = useState()

    useEffect(() => {
        const getData = async () => {
            const querySnapshot = await getDocs(collection(db, 'users/kvv.prof@gmail.com/todos'))
            const todos = []
            querySnapshot.forEach(doc => {
                todos.push({
                    id: doc.id,
                    text: doc.data().text,
                    isCompleted: doc.data().isCompleted,
                })
            })
            return setTodos(todos)
        }
        getData()
    }, [])

    return (
        <section className="todo-list">
            {todos?.map(todo => (
                <Todo key={todo.id} id={todo.id} text={todo.text} isCompleted={todo.isCompleted} />
            ))}
        </section>
    )
}

export default TodoList

If you use react-firebase-hooks, then you need to use this

Related