How to declare a variable from a firestore query?

Tags: , , ,



this piece of code works when I press save in visual studio code. But If I refresh the preview page in the browser it shows me this error: Unhandled Rejection (FirebaseError): Function Query.where() called with invalid data. Unsupported field value: undefined

let { id } = useParams();
const  = React.useState([]);
const [show, setShow] = React.useState([]);
const classes = useStyles();

React.useEffect(() => {
    const fetchData = async () => {
      const db = firebase.firestore();
      const data = await db
      .collection("videos")
      .where('path', '==', id)
      .get()
      setVideo(data.docs.map(doc => doc.data()));
    }
    fetchData()
    
  }, [])

let showUrl = video.map(video =>(video.uploadBy));
console.log(showUrl[0]);
let videoDate = video.map(video =>(video.date.toDate()));
console.log(videoDate[0]);

React.useEffect(() => {
    const fetchData = async () => {
      const db = firebase.firestore();
      const data = await db
      .collection("shows")
      .where('urlPath', '==', showUrl[0])
      .get()
      setShow(data.docs.map(doc => doc.data()));
    }
    fetchData()
  }, [])

I think that the problem is that I’m trying to declare the variable “showUrl” in the wrong way. The console.log(showUrl[0]) works perfectly. It prints exactly the value that I need.

Answer

Both these useEffect calls fire as soon as the component mounts. If you are getting the id for your first useEffect from url parameters or such, it’s probably there immediately and the call Firestore query should work.

However, when your second useEffect fires, the state ‘video’ is still set to an empty array. Therefore the showUrl variable is also an empty array, and showUrl[0] is undefined.

What you could do for your second useEffect is this:

   React.useEffect(() => {
    const fetchData = async () => {
      const db = firebase.firestore();
      const data = await db
      .collection("shows")
      .where('urlPath', '==', showUrl[0])
      .get()
      setShow(data.docs.map(doc => doc.data()));
    }
    video.length && fetchData()
   }, )

So you are only calling the fetchData() function if the array in ‘video’ state has more than 0 items, and you add it to the useEffect dependency array, so the useEffect gets ran every time ‘video’ changes.



Source: stackoverflow