I am creating a Todo list using React and Firebase. So far, I have already created the AddToDo functionality, however, now I am having trouble with the delete functionality. I believe this is where my problem lies. For example, when I try and click the delete icon that I set up, I get an error:
Unhandled Runtime Error TypeError: Cannot read properties of undefined (reading 'id')
This is the code if it helps. AddLink.js
import { useState, useEffect } from "react"; import classes from "./addlink.module.css"; import firebase from "firebase/app"; import initFirebase from "../../config"; import "firebase/firestore"; import Todo from "../Todo/Todo"; import { v4 as uuidv4 } from "uuid"; initFirebase(); const db = firebase.firestore(); function AddLink(props) { const [todos, setTodos] = useState([]); const [input, setInput] = useState(""); useEffect(() => { db.collection("links") .orderBy("timestamp", "desc") .onSnapshot((snapshot) => { // this gives back an array setTodos( snapshot.docs.map((doc) => ({ id: doc.id, todo: doc.data().todo, })) ); }); }, []); const addTodo = (event) => { event.preventDefault(); console.log("clicked"); db.collection("links").add({ id: uuidv4(), todo: input, timestamp: firebase.firestore.FieldValue.serverTimestamp(), }); setInput(""); }; return ( <div className={classes.addlink}> <form> <div className={classes.adminlink}> <input type="text" value={input} onChange={(event) => setInput(event.target.value)} /> <button className={classes.adminbutton} type="submit" onClick={addTodo} > Add new link </button> </div> </form> {todos.map((todo, id) => ( <Todo value={todo} key={id} /> ))} {/* {modalIsOpen && ( <Modal onCancel={closeModalHandler} onConfirm={closeModalHandler} /> )} {modalIsOpen && <Backdrop onCancel={closeModalHandler} />} */} </div> ); } export default AddLink;
And Todo.js
import React from "react"; import { AiOutlinePicture } from "react-icons/ai"; import { AiOutlineStar } from "react-icons/ai"; import { GoGraph } from "react-icons/go"; import DeleteForeverIcon from "@material-ui/icons/DeleteForever"; import classes from "./todo.module.css"; import firebase from "firebase/app"; import initFirebase from "../../config"; import "firebase/firestore"; initFirebase(); const db = firebase.firestore(); function Todo(props) { const deleteHandler = () => { db.collection("todos").doc(props.todo.id).delete(); }; return ( <li className={classes.adminsection}> <div className={classes.linkCards}> <h3>{props.text}</h3> <p>This is a new link</p> <div> <AiOutlinePicture /> <AiOutlineStar /> <GoGraph /> <DeleteForeverIcon onClick={deleteHandler} /> </div> </div> </li> ); } export default Todo;
Any help would be greatly appreciated.
Advertisement
Answer
const deleteHandler = () => { db.collection("todos").doc(props.todo.id).delete(); };
You should replace props.todo.id
with props.value.id
.
const deleteHandler = () => { db.collection("todos").doc(props.value.id).delete(); };
Alternatively you can change:
<Todo value={todo} key={id} />
To
<Todo todo={todo} key={id} />
The key you use to access props.value
should be the same as the one declared in the jsx template. Using proptypes can help you avoid those mistakes.