I'm trying to figure out how to read firestore sub collection data from react.
I have seen this blog that describes how to do it and am now trying to figure out how to implement the logic of it.
I have a parent collection called glossary and a sub collection within it called relatedTerms.
I have a form that works to correctly submit data to the glossary and relatedTerms collections with the exception that I can't find a way to post the value of the glossary id as an attribute on the relatedTerms document. My current attempt at doing that is:
onSubmit={(values, { setSubmitting }) => {
setSubmitting(true);
// firestore.collection("glossary").doc().set({
// ...values,
// createdAt: firebase.firestore.FieldValue.serverTimestamp()
// })
// .then(() => {
// setSubmitionCompleted(true);
// });
// }}
const newDocRef = firestore.collection("glossary").doc() // auto generated doc id saved here
let writeBatch = firestore.batch();
{console.log("logging values:", values)};
writeBatch.set(newDocRef,{
term: values.term,
definition: values.definition,
category: values.category,
context: values.context,
createdAt: firebase.firestore.FieldValue.serverTimestamp()
});
writeBatch.set(newDocRef.collection('relatedTerms').doc(),{
// dataType: values.dataType,
// title: values.title,
glossaryId: newDocRef.id,
...values.relatedTerms
// description: values.description,
})
writeBatch.commit()
.then(() => {
setSubmitionCompleted(true);
});
}}
No error message is shared when I try this, the glossaryId just gets ignored. It remains a mystery to me what the batch concept is- I thought it only ran if all the instructions could be performed.
I'm trying to figure out how to access the data stored in the sub collection. My current attempt at doing that is based on the example in the post linked above.
import React, { useState, useEffect } from 'react';
import {Link } from 'react-router-dom';
import Typography from '@material-ui/core/Typography';
import firebase, { firestore } from "../../../../firebase.js";
import { makeStyles } from '@material-ui/core/styles';
import clsx from 'clsx';
const useStyles = makeStyles((theme) => ({
root: {
width: '100%',
marginTop: '8vh',
marginBottom: '5vh'
},
}));
function useGlossaryTerms() {
const [glossaryTerms, setGlossaryTerms] = useState([])
const [relatedGlossaryTerms, setRelatedGlossaryTerms] = useState([])
useEffect(() => {
firebase
.firestore()
.collection("glossary")
.orderBy('term')
.onSnapshot(snapshot => {
const glossaryTerms = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setGlossaryTerms(glossaryTerms)
});
// setRelatedGlossaryTerms(glossaryTerms)
}, [])
return glossaryTerms;
}
const relatedTermsList = (glossaryTerm) => {
setGlossaryTerms(glossaryTerm);
firebase.firestore().collection('glossary').doc(glossaryTerm.id).collection('relatedTerms').get()
.then(response => {
const relatedGlossaryTerms = [];
response.forEach(document => {
const relatedGlossaryTerm = {
id: document.id,
...document.data()
};
relatedGlossaryTerms.push(relatedGlossaryTerm);
});
setRelatedGlossaryTerms(relatedGlossaryTerms);
})
.catch(error => {
// setError(error);
});
}
const GlossaryTerms = () => {
const glossaryTerms = useGlossaryTerms()
const relatedGlossaryTerms = useGlossaryTerms()
const classes = useStyles();
return (
<div>
{glossaryTerms.map(glossaryTerm => {
return (
{glossaryTerm.term}
{glossaryTerm.category.map(category => (
{category.label}
)
)}
</div>
{glossaryTerm.definition}
{glossaryTerm ? (
<ul>
{relatedGlossaryTerms.map(relatedGlossaryTerm => (
<li key={relatedGlossaryTerm.id}>
{relatedGlossaryTerm.title} | {relatedGlossaryTerm.description}
</li>
))}
</ul>
) : null}
)
})}
</div>
);
}
export default GlossaryTerms;
When I try this, I get error messages saying that in my relatedTermsList const, the definitions of setGlossaryTerms and setRelatedGlossaryTerms are undefined.
Each of these errors are odd to me because setRelatedGlossaryTerms is defined in the same way as setGlossaryTerms. I don't understand why it is unrecognisable and setGlossaryTerms is used in the useEffect without any issue.
NEXT ATTEMPT
I tried using a second useEffect function that takes a glossaryTerm.
function useGlossaryTerms() {
const [glossaryTerms, setGlossaryTerms] = useState([])
const [relatedGlossaryTerms, setRelatedGlossaryTerms] = useState([])
useEffect(() => {
firebase
.firestore()
.collection("glossary")
.orderBy('term')
.onSnapshot(snapshot => {
const glossaryTerms = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setGlossaryTerms(glossaryTerms)
});
// setRelatedGlossaryTerms(glossaryTerms)
}, [])
return glossaryTerms;
}
useEffect((glossaryTerm) => {
firebase
.firestore()
.collection("glossary")
.doc(glossaryTerm.id)
.collection('relatedTerms')
.onSnapshot(snapshot => {
const relatedGlossaryTerms = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data(),
}))
setRelatedGlossaryTerms(relatedGlossaryTerms)
})
.catch(error => {
// setError(error);
});
});
const GlossaryTerms = () => {
const glossaryTerms = useGlossaryTerms()
const relatedGlossaryTerms = useGlossaryTerms()
const classes = useStyles();
return (
I don't understand why, but the error is that setRelatedGlossaryTerms is not defined - where it's used in the second useEffect.
from Reading firestore sub-collection data in react
No comments:
Post a Comment