I have a firestore database with the following structure.

What I want to do is to update the chosen value when the user clicks a button. I have the new value I want to add, but I am getting errors.
<button className='buttonCheck' onClick={checkAnswer}>CHECK MY ANSWER</button>
when I click the button it calls the "checkAnswer" function
function AnswerComponent(props) {
let totalNoAnswers = props.totalAnswers;
let answers = props.answersarray;
const [valueA, setValue] = useState() // make this mean something better
const [showCongratsModal, setShowCongratsModal] = useState(false);
const [showCongratsURL, setShowCongratsURL] = useState("")
const [showWindowContent, setShowWindowContent] = useState("")
const [selectedAnswerGroup, setSelectedAnswerGroup] = useState("")
const [chosenCount, setChosenCount]= useState()
function checkAnswer() {
setShowCongratsModal(true)
if (valueA === true) {
setShowCongratsURL("https://firebasestorage.googleapis.com/v0/b/assignment219000170.appspot.com/o/videos%2Fcongrat_w3_s.mp4?alt=media&token=034ea1bc-b3e0-4b51-957f-854dae963896")
} else if (valueA === false) {
setShowWindowContent("Incorrect answer - please try again.")
} else {
setShowWindowContent("Please choose an answer before proceeding.")
}
const updateFirestore = async () => {
const db = firebase.firestore();
const collectionId = "Questions";
const documentId = "balances";
const snapshot = db.collection(collectionId).doc(documentId);
console.log("> ", snapshot)
console.log(">> ", selectedAnswerGroup)
const res = await snapshot.set({
balances: {
balances: {
answers: {
[selectedAnswerGroup]: {
chosen: chosenCount
}
}
}
}
}, {merge: true})
console.log("1", res)
}
updateFirestore()
}
The variable selectedAnswerGroup contains "answer_1" - and "chosenCount" will contain a new number, so using the above, I thought I would update the database.
However,I get an error on the console Uncaught (in promise) TypeError: firestore.collection(...).doc(...).balances is undefined
I can't see what I have done wrong.
Do I need to contain this in a firebase.auth() block?
You're getting this error: TypeError: firestore.collection(...).doc(...).balances is undefined because of the way you construct your reference.
This is the line of code you're having an error:
const snapshot = await firestore.collection(collectionId).doc(documentId).balances.balances.answers[selectedAnswerGroup]
TypeError: undefined occurs when a property is read or a function is called on an undefined variable. You're using a dot notation to access a method so it reads balances as a method.
Your reference should always be following this pattern:
db.collection("main_collection").doc("main_collection's_document").collection("sub_collection").doc("sub_collection's_document");
Checkout Cloud Firestore Data model, this is a good way to start building a reference to your Firestore Data Structure.
For you to update a specific field inside the map of an object, you have to define the document identifier and build a map based on your Firestore Data Structure. See code below:
function checkAnswer() {
setShowCongratsModal(true)
if (valueA === true) {
setShowCongratsURL("https://firebasestorage.googleapis.com/v0/b/assignment219000170.appspot.com/o/videos%2Fcongrat_w3_s.mp4?alt=media&token=034ea1bc-b3e0-4b51-957f-854dae963896")
} else if (valueA === false) {
setShowWindowContent("Incorrect answer - please try again.")
} else {
setShowWindowContent("Please choose an answer before proceeding.")
}
updateFirestore()
.then((snapshot) => {
console.log('updateFirestore() successfully called!');
console.log(snapshot);
})
.catch((e) => {
console.log(e);
});
}
async function updateFirestore() {
const db = firebase.firestore();
const collectionId = "Questions";
const documentId = "balances";
// You could also log something here to ensure that this async function has been ran.
// console.log(selectedAnswerGroup);
// console.log(chosenCount);
const snapshot = db
.collection(collectionId)
.doc(documentId)
.set(
{
balances: {
balances: {
answers: {
[selectedAnswerGroup]: {
chosen: chosenCount
}
}
}
}
}, {merge: true});
return snapshot;
}
You may check Set a document and Update fields in nested objects documentations for more information.