首页 > 解决方案 > 如何使反应停止点击重复元素

问题描述

问题是每次我点击一个有状态的元素时,都会出现两次。例如,如果我单击一个按钮并且单击的结果是在控制台中输出某些内容,它将输出 2 次。但是在这种情况下,每当我单击一个函数时,都会执行两次。

编码:

const getfiles = async () => {
    let a = await documentSpecifics;

    for(let i = 0; i < a.length; i++) {
        var wrt = document.querySelectorAll("#writeto");
        var fd = document.querySelector('.filtered-docs');
        var newResultEl = document.createElement('div');
        var writeToEl = document.createElement('p');
        newResultEl.classList.add("result");
        writeToEl.id = "writeto";
        newResultEl.appendChild(writeToEl);
        fd.appendChild(newResultEl);
        listOfNodes.push(writeToEl);
        listOfContainers.push(newResultEl);
        wrt[i].textContent = a[i].data.documentName;                        
     }
}

这里的代码应该创建一个带有段落标签的新 div 元素并从 firebase firestore 获取数据,并将数据写入 p 标签。现在,如果 Firestore 中有 9 个文档并且我单击一个按钮,那么将复制另外 9 个 div。现在总共有 18 个 div,只有 9 个包含实际数据,其余的都是空白的。每次点击它都会继续创建另外 9 个 div。我也知道React.Strictmode这样做是为了进行一些调试,但我确保将其取出并仍然得到相同的结果。火力基地代码:

//put data in firebase
createFileToDb = () => {
        var docName = document.getElementById("title-custom").value; //get values
        var specifiedWidth = document.getElementById("doc-width").value;
        var specifiedHeight = document.getElementById("doc-height").value;
        var colorType = document.getElementById("select-color").value;

        parseInt(specifiedWidth); //transform strings to integers
        parseInt(specifiedHeight);
        
        firebase.firestore().collection("documents")
        .doc(firebase.auth().currentUser.uid)
        .collection("userDocs")
        .add({
            documentName: docName,
            width: Number(specifiedWidth), //firebase-firestore method for converting the type of value in the firestore databse
            height: Number(specifiedHeight),
            docColorType: colorType,
            creation: firebase.firestore.FieldValue.serverTimestamp() // it is possible that this is necessary in order to use "orderBy" when getting data
        }).then(() => {
            console.log("file in database");
        }).catch(() => {
            console.log("failed");
        })
    }

//get data
GetData = () => {
        return firebase.firestore()
        .collection("documents")
        .doc(firebase.auth().currentUser.uid)
        .collection("userDocs")
        .orderBy("creation", "asc")
        .get()
        .then((doc) => {
            let custom = doc.docs.map((document) => {
                var data = document.data();
                var id = document.id;
                return { id, data }
            })
            return custom;
            
        }).catch((err) => {console.error(err)});

    }

waitForData = async () => {
        let result = await this.GetData();
        return result;
}
//in render
let documentSpecifics = this.waitForData().then((response) => response)
        .then((u) => {
            if(u.length > 0) {
                for(let i = 0; i < u.length; i++) {
                    try {
                        //
                    } catch(error) {
                        console.log(error);
                    }
                }
                
            }
            return u;
        });

编辑:firebase auth 运行良好,所以我认为它与问题没有任何关系编辑:这一切都在一个类组件中编辑:单击一个按钮调用该函数createFileToDb

标签: javascriptreactjsfirebasefor-loopgoogle-cloud-firestore

解决方案


我想我找到了问题的答案。基本上,因为这是一个类组件,所以我从渲染中取出了一些东西并放置了一些console.log语句来看看发生了什么。我注意到的是它在渲染中记录了两次,但不在它之外。所以我把功能拿出来了。这是似乎可以解决我的问题的代码:

contain = () => {
        const documentSpecifics = this.waitForData().then((response) => {
            var wrt = document.getElementsByClassName('writeto');
            for(let i = 0; i < response.length; i++) {
                this.setNewFile();
                wrt[i].textContent = response[i].data.documentName;
            }

            return response;
        })
        this.setState({
            docs: documentSpecifics,
            docDisplayType: !this.state.docDisplayType
        })
    }

至于创建元素,我将它们放在一个函数中,以便我可以重用它:

setNewFile = () => {
        const wrt = document.querySelector(".writeto");
        const fd = document.querySelector("#filtered-docs");
        var newResultEl = document.createElement('div');
        newResultEl.classList.add("result");
        var wrtEl = document.createElement('p');
        wrtEl.classList.add("writeto");
        fd.appendChild(newResultEl);
        newResultEl.appendChild(wrtEl);
    }

firebase 和 firestore 代码保持不变。使用 onClick 通过返回中的元素调用这些函数。


推荐阅读