skip to Main Content

I’m working on a to-do list app in React that connects to a Firestore Database and I’m able to send the data correctly to Firebase, but my {task.name} is not displaying. The list numbers and the button are loading, but not {task.name}. The tasks are added to Firebase with the handleAdd function and the tasks are supposed to be loaded with the useEffect function. Here is the code for the main to-do.js file:

import React, { useEffect } from "react";
import { useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { db } from "./utils/firebase";
import { collection, addDoc, Timestamp, query, orderBy, onSnapshot } from "firebase/firestore";

export default function Todo() {

const [name, setName] = useState("");
const [isDoubleClicked, setDoubleClicked] = useState(false);

const [tasks, setTasks] = useState([]);

function handleChange(event) {
    event.preventDefault();
    setName(event.target.value);

}

const handleAdd = async (e, id) => {
    e.preventDefault();
    try {
        await addDoc(collection(db, 'tasks'), {
            name: name,
            id: uuidv4(),
            completed: false,
            created: Timestamp.now(),
        })
    } catch (err) {
        alert(err)
    }
}

useEffect(() => {
    const q = query(collection(db, 'tasks'), orderBy('created', 'name'))
    onSnapshot(q, (querySnapshot) => {
        setTasks(querySnapshot.docs.map(doc => ({
            id: doc.id,
            data: doc.data()
        })))
    })
    console.log(tasks);
}, [])

function handleClick(event) {
    if (event.detail === 2) {
        console.log("double click");
        setDoubleClicked(current => !current);
        event.currentTarget.classList.toggle('double-clicked');
    }
}

return (
    <div>
        <div>
            <div>
                <h1>To Do List App</h1>
                <p>Double click to mark an item off, click on "X" to delete an item, and drag items to reorder.</p>
            </div>
            <input
                type="text"
                value={name}
                onChange={handleChange}
            />
            <button
                type="submit"
                onClick={handleAdd}
            >
                Add
            </button>
        </div>

        <ol>
            {tasks.map((task => (
                <li
                    id={task.id}
                    key={task.id}
                    completed={task.data.completed}
                    onClick={handleClick}
                >
                    {task.name} <button>x</button>
                </li>
            )))}
        </ol>

    </div>
);
};

2

Answers


  1. Chosen as BEST ANSWER

    I figured this out. I had to change {task.name} to {task.data.name}. I also updated the useEffect function. Here is the code:

    import React, { useEffect } from "react";
    import { useState } from "react";
    import { v4 as uuidv4 } from "uuid";
    import { db } from "./utils/firebase";
    import { collection, addDoc, Timestamp, query, orderBy, onSnapshot } from "firebase/firestore";
    
    export default function Todo() {
    
        const [name, setName] = useState("");
        const [isDoubleClicked, setDoubleClicked] = useState(false);
    
        const [tasks, setTasks] = useState([]);
    
        function handleChange(event) {
            event.preventDefault();
            setName(event.target.value);
    
        }
    
        const handleAdd = async (e, id) => {
            e.preventDefault();
            try {
                await addDoc(collection(db, 'tasks'), {
                    name: name,
                    id: uuidv4(),
                    completed: false,
                    created: Timestamp.now(),
                })
            } catch (err) {
                alert(err)
            }
        }
    
        useEffect(() => {
            const q = query(collection(db, 'tasks'), orderBy('created'))
            onSnapshot(q, (querySnapshot) => {
                setTasks(querySnapshot.docs.map(doc => ({
                    data: doc.data()
                })))
            })
            console.log(tasks);
        }, [])
    
        function handleClick(event) {
            if (event.detail === 2) {
                console.log("double click");
                setDoubleClicked(current => !current);
                event.currentTarget.classList.toggle('double-clicked');
            }
        }
    
        return (
            <div>
                <div>
                    <div>
                        <h1>To Do List App</h1>
                        <p>Double click to mark an item off, click on "X" to delete an item, and drag items to reorder.</p>
                    </div>
                    <input
                        type="text"
                        value={name}
                        onChange={handleChange}
                    />
                    <button
                        type="submit"
                        onClick={handleAdd}
                    >
                        Add
                    </button>
                </div>
    
                <ol>
                    {tasks.map((task => (
                        <li
                            id={task.data.id}
                            key={task.data.id}
                            completed={task.data.completed}
                            onClick={handleClick}
                        >
                            {task.data.name} <button>x</button>
                        </li>
                    )))}
                </ol>
    
            </div>
        );
    };
    

  2. as far as I can tell you are setting task the wrong way, instated of mapping to data stay consistent with the original uploading logic, to avoid such cases you can type your state for the sake of consistency.

    useEffect(() => {
        const q = query(collection(db, 'tasks'), orderBy('created', 'name'))
        onSnapshot(q, (querySnapshot) => {
            setTasks(querySnapshot.docs.map(doc => ({
                name: doc.data().name,
                id: doc.data().id,
                completed: doc.data().completed,
                created: doc.data().created,
         })))
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search