Reactjs 每次用户登录时firebase DB中的新节点
我正在React中创建测试/检查应用程序。这些问题是预定义的,并存储在一个节点的firebase数据库中,我想将进行的测试存储在另一个节点中。但是我想为每次新的考试尝试添加新的子节点 不幸的是,到目前为止,结果已被取代 我需要这样的结构:Reactjs 每次用户登录时firebase DB中的新节点,reactjs,firebase,Reactjs,Firebase,我正在React中创建测试/检查应用程序。这些问题是预定义的,并存储在一个节点的firebase数据库中,我想将进行的测试存储在另一个节点中。但是我想为每次新的考试尝试添加新的子节点 不幸的是,到目前为止,结果已被取代 我需要这样的结构: "answers": { "0": { "user": "Mr X", "testDone": true, "result": 3, "questions": { "0": {
"answers": {
"0": {
"user": "Mr X",
"testDone": true,
"result": 3,
"questions": {
"0": {
"content": "How much is 2 x 2?",
"selectedAnswer": "A",
"correctAnswer": "A"
},
"1": {
"content": "How much is 2 + 2?",
"selectedAnswer": "B",
"correctAnswer": "B"
},
"2": {
"content": "How much is 2 / 2?",
"selectedAnswer": "C",
"correctAnswer": "C"
}
}
},
"1": {
"user": "Mr Y",
"testDone": true,
"result": 1,
"questions": {
"0": {
"content": "How much is 2 x 2?",
"selectedAnswer": "A",
"correctAnswer": "A"
},
"1": {
"content": "How much is 2 + 2?",
"selectedAnswer": "C",
"correctAnswer": "B"
},
"2": {
"content": "How much is 2 / 2?",
"selectedAnswer": "B",
"correctAnswer": "C"
}
}
},
"2": {
"user": "Mr Z",
"testDone": true,
"result": 2,
"questions": {
"0": {
"content": "How much is 2 x 2?",
"selectedAnswer": "A",
"correctAnswer": "A"
},
"1": {
"content": "How much is 2 + 2?",
"selectedAnswer": "B",
"correctAnswer": "B"
},
"2": {
"content": "How much is 2 / 2?",
"selectedAnswer": "A",
"correctAnswer": "C"
}
}
}
}
}
在未来,我还想防止用户进行一次以上的考试。因此,我需要在身份验证过程中检查特定用户名是否已存在于answers对象中,或者预定义answers对象,并仅对位于该对象内且属性testDone的值设置为false的用户进行身份验证
因此,我的问题是如何强制firebase为新的考试尝试添加新节点,然后将应用程序状态与特定子节点同步(每次不同的子节点将被同步)。您可以有一个节点只用于测试结果,每次用户参加测试,它们的结果将使用每个新结果的唯一ID添加到该节点。这样,它们将不会覆盖以前保存的结果,您也可以将用户ID绑定到结果
//Database reference
var firebaseDb = firebase.database().ref.child("completed_tests");
//example score from a test
var usersScore = 9;
//Creating a new reference with a newly generated key, unique to this node.
var resultsRef = firebaseDb.push();
//Getting the unique key so we can use it to save data to it.
var newId = resultsRef.key;
//Adding data to the node we created above, inside the "completed_tests" node.
firebaseDb.child(newId).child("grade").set(userScore);
数据库可能类似于此示例
{
"root": {
"completed_tests": {
"uniqueTestId_12345": {
"Which_test": "test_1",
"userId": "1234_uid_of_test_taker",
"grade": 9
},
"uniqueTestId_23456": {
"grade": 5
},
"uniqueTestId_34567": {
"grade": 7
}
},
"tests": {
"test_1": {
"Q1": "Who am I?",
"Q2": "..."
},
"test_2": {
"Q1": "Who are You?",
"Q2": "..."
}
}
}
}
上面是一个使用JavaScript使用唯一ID保存数据的简单示例。显然,您可以将更多数据保存到节点,可能是单个答案、分数、时间戳、uid、指向原始测试的指针等。谢谢您的回答。现在,我的componentDidMount()函数如下所示:
componentDidMount() {
var firebaseDb = firebaseApp.database().ref("completed_tests");
var resultsRef = firebaseDb.push();
var newId = resultsRef.key;
this.ref = fbase.syncState("/completed_tests/" + newId + "/user/", {
context: this,
asArray: true,
state: "user"
});
this.ref = fbase.syncState("/completed_tests/" + newId + "/answers/", {
context: this,
asArray: true,
state: "answers"
});
this.ref = fbase.syncState("/completed_tests/" + newId + "/result/", {
context: this,
asArray: true,
state: "result"
});
}
它工作得很好,但还有一件事我想改进。现在,每个节点引用都由奇怪的字符串组成。我更希望节点的名称与登录名(电子邮件地址)相同,但当然要将“.”替换为firabase允许的任何符号(即“”)。因此,我将身份验证功能更改为:
authenticate = event => {
event.preventDefault();
firebaseApp
.auth()
.signInWithEmailAndPassword(this.state.email, this.state.password)
.then(() => {
this.setState({
loggedIn: 1,
user: this.state.email
});
})
.catch(() => {
console.log("Unable to authenticate");
});
firebaseApp
.database()
.ref("/users/")
.once("value")
.then(snapshot => {
for (var key in snapshot.val()) {
if (this.state.email.replace(".", "_") === key) {
this.setState({
loggedIn: 2
});
console.log("you have already filled the test");
} else {
console.log("it's first time you arte taking this test");
}
}
});
};
loggedinstate的值用于控制要显示的内容,因此我可以防止用户多次参加测试。但现在我想添加新节点(即用户登录)并将所有其他对象发送到其中。添加此节点不是问题,但我无法通过此新节点的绑定状态。如果我把它放在authenticate函数中,它就不起作用了,因为身份验证是在添加绑定代码之后进行的。
componentDidMount()内部的绑定也不起作用,因为在调用componentDidMount()函数后,连接到登录名的状态值发生了更改
有什么方法可以克服这个问题吗?您的代码中有哪些没有按预期的方式工作?请将您的问题编辑为具体问题。