reactjs 添加功能后,React Firebase to do list应用程序变慢

ar7v8xwq  于 2023-01-05  发布在  React
关注(0)|答案(1)|浏览(115)

我一直在开发一个带有身份验证的to-do列表应用程序,在我添加了“通过UID和searchInput搜索数据库的功能”之前,一切都运行良好。该应用程序允许用户添加、编辑、删除和搜索存储在Firebase中的任务。有两个集合,任务和用户,它们通过UID相互连接。以下是ToDo.js中的代码:

import React, { useEffect, useState } from "react";
import { collection, doc, addDoc, updateDoc, deleteDoc, Timestamp, query, orderBy, onSnapshot, where } from "firebase/firestore";
import { BsFillPencilFill, BsFillTrashFill } from "react-icons/bs";
import { IoMdAddCircle } from "react-icons/io";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, db, logout } from "./utils/firebase";

export default function Todo() {

    const [name, setName] = useState("");
    const [tasks, setTasks] = useState([]);
    const [user, loading, error] = useAuthState(auth);
    const [searchInput, setSearchInput] = useState("");

    //function for automatically retrieving items
    useEffect(() => {
        getCollectionById();
    }, [])

    //search database by UID
    function getCollectionById() {
        const q = query(collection(db, 'tasks'), where("uid", "==", user?.uid));
        onSnapshot(q, (querySnapshot) => {
            setTasks(querySnapshot.docs.map(doc => ({
                id: doc.id,
                data: doc.data()
            })))
        })
    }

    //function for getting the value of the main input
    function handleChange(e) {
        e.preventDefault();
        setName(e.target.value);
        console.log(name);
    }

    //function for getting the value of the search input
    function handleSearchChange(e) {
        e.preventDefault();
        setSearchInput(e.target.value)
    }

    //function for searching database by UID and searchInput
    if (searchInput.length > 0) {
        const q = query(collection(db, 'tasks'), where("uid", "==", user?.uid), where("name", ">=", searchInput), where("name", "<=", searchInput + '\uf8ff'));
        onSnapshot(q, (querySnapshot) => {
            setTasks(querySnapshot.docs.map(doc => ({
                id: doc.id,
                data: doc.data()
            })))
        })
    } else {
        getCollectionById();
    }

    //function for adding items to firestore
    const handleAdd = async (e) => {
        e.preventDefault();
        if (name === "") {
            alert("Please enter some text");
            clearInput();
            return;
        }
        try {
            await addDoc(collection(db, 'tasks'), {
                name: name,
                completed: false,
                created: Timestamp.now(),
                uid: user?.uid,
            })
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for adding strikethrough to an item
    function handleClick(e) {
        if (e.detail === 2) {
            console.log("double click");
            e.currentTarget.classList.toggle('double-clicked');
        }
    }

    //function for updating an item
    const handleUpdate = async (taskName, id) => {
        let name = prompt("Please enter a new name", taskName);
        if (name === null) {
            return;
        }
        const taskDocRef = doc(db, 'tasks', id)
        try {
            await updateDoc(taskDocRef, {
                name: name,
            })
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for deleting an item
    const handleDelete = async (id) => {
        console.log(id);
        const taskDocRef = doc(db, 'tasks', id)
        try {
            await deleteDoc(taskDocRef)
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for clearing and focusing the input
    function clearInput() {
        let input = document.querySelector("input");
        input.value = '';
        input.focus();
        setName("");
    }

    return (
        <div>
            <div>
                <div>
                    <h1>To Do List App</h1>
                    <p>Double click to mark an item off.</p>
                </div>
                <input
                    id="input"
                    type="text"
                    value={name}
                    onChange={handleChange}
                    autoFocus
                />
                <button
                    className="add-button"
                    type="submit"
                    onClick={handleAdd}
                >
                    <IoMdAddCircle />
                </button>
            </div>

            <ol>
                {tasks.map((task) => (
                    <li
                        class="task-list-items"
                        id={task.id}
                        key={task.id}
                        completed={task.data.completed}
                        onClick={handleClick}
                    >
                        {task.data.name}
                        <button
                            className="edit-button"
                            onClick={() => handleUpdate(task.data.name, task.id)}
                        >
                            <BsFillPencilFill />
                        </button>
                        <button
                            className="delete-button"
                            onClick={() => handleDelete(task.id)}
                        >
                            <BsFillTrashFill />
                        </button>
                    </li>
                ))}
            </ol>

            <div>
                <h5>Search for an item by name</h5>
                <input
                    id="search-bar"
                    type="text"
                    value={searchInput}
                    onChange={handleSearchChange}
                />
            </div>

        </div>
    );
};
xqk2d5yq

xqk2d5yq1#

我可以通过过滤任务数组而不是搜索数据库来解决这个问题。下面是我更新的代码:

import React, { useEffect, useState } from "react";
import { collection, doc, addDoc, updateDoc, deleteDoc, Timestamp, query, orderBy, onSnapshot, where } from "firebase/firestore";
import { BsFillPencilFill, BsFillTrashFill } from "react-icons/bs";
import { IoMdAddCircle } from "react-icons/io";
import { useAuthState } from "react-firebase-hooks/auth";
import { auth, db, logout } from "./utils/firebase";

export default function Todo() {

    const [name, setName] = useState("");
    const [tasks, setTasks] = useState([]);
    const [user, loading, error] = useAuthState(auth);
    const [searchInput, setSearchInput] = useState("");

    //function for automatically retrieving items
    useEffect(() => {
        const q = query(collection(db, 'tasks'), where("uid", "==", user?.uid));
        onSnapshot(q, (querySnapshot) => {
            setTasks(querySnapshot.docs.map(doc => ({
                id: doc.id,
                data: doc.data()
            })))
        })
    }, [])

    //function for getting the value of the main input
    function handleChange(e) {
        e.preventDefault();
        setName(e.target.value);
        console.log(name);
    }

    //function for getting the value of the search input
    function handleSearchChange(e) {
        e.preventDefault();
        setSearchInput(e.target.value)
    }

    //function for adding items to firestore
    const handleAdd = async (e) => {
        e.preventDefault();
        if (name === "") {
            alert("Please enter some text");
            clearInput();
            return;
        }
        try {
            await addDoc(collection(db, 'tasks'), {
                name: name,
                completed: false,
                created: Timestamp.now(),
                uid: user?.uid,
            })
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for adding strikethrough to an item
    function handleClick(e) {
        if (e.detail === 2) {
            console.log("double click");
            e.currentTarget.classList.toggle('double-clicked');
        }
    }

    //function for updating an item
    const handleUpdate = async (taskName, id) => {
        let name = prompt("Please enter a new name", taskName);
        if (name === null) {
            return;
        }
        const taskDocRef = doc(db, 'tasks', id)
        try {
            await updateDoc(taskDocRef, {
                name: name,
            })
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for deleting an item
    const handleDelete = async (id) => {
        console.log(id);
        const taskDocRef = doc(db, 'tasks', id)
        try {
            await deleteDoc(taskDocRef)
            clearInput();
        } catch (err) {
            alert(err)
        }
    }

    //function for clearing and focusing the input
    function clearInput() {
        let input = document.querySelector("input");
        input.value = '';
        input.focus();
        setName("");
    }

    return (
        <div>
            <div>
                <div>
                    <h1>To Do List App</h1>
                    <p>Double click to mark an item off.</p>
                </div>
                <input
                    id="input"
                    type="text"
                    value={name}
                    onChange={handleChange}
                    autoFocus
                />
                <button
                    className="add-button"
                    type="submit"
                    onClick={handleAdd}
                >
                    <IoMdAddCircle />
                </button>
            </div>

            <ol>
                {tasks.filter(task => task.data.name.includes(searchInput)).map(task => (
                    <li
                        className="task-list-items"
                        id={task.id}
                        key={task.id}
                        completed={task.data.completed}
                        onClick={handleClick}
                    >
                        {task.data.name}
                        <button
                            className="edit-button"
                            onClick={() => handleUpdate(task.data.name, task.id)}
                        >
                            <BsFillPencilFill />
                        </button>
                        <button
                            className="delete-button"
                            onClick={() => handleDelete(task.id)}
                        >
                            <BsFillTrashFill />
                        </button>
                    </li>
                ))}
            </ol>

            <div>
                <h5>Search for an item by name</h5>
                <input
                    id="search-bar"
                    type="text"
                    value={searchInput}
                    onChange={handleSearchChange}
                />
            </div>

        </div>
    );
};

相关问题