0

EDIT: Now the daily page is blank and I'm getting an error of a.indexOf is not a function...no idea what that even means...

prebuilt-ac190846-5fb4dac2.js:719 Uncaught TypeError: a.indexOf is not a function
    at Function.t.fromString (prebuilt-ac190846-5fb4dac2.js:719)
    at Tu (prebuilt-ac190846-5fb4dac2.js:14976)
    at t.doc (prebuilt-ac190846-5fb4dac2.js:18193)
    at ConfidenceTexts.js:20
    at Os (react-dom.production.min.js:262)
    at t.unstable_runWithPriority (scheduler.production.min.js:18)
    at Qi (react-dom.production.min.js:122)
    at Rs (react-dom.production.min.js:261)
    at react-dom.production.min.js:261
    at L (scheduler.production.min.js:16)

I have looked at multiple tutorials, and I'm still a bit baffled on how to get my app to show what I want. I eventually want to have a database with a bunch of quotes, and my app to randomly pick one to display.

I have managed to setup a collection in Firestore that always has one doc called 'num' with a field called num and the value is a stringified number. I'm using a Firebase cloud function to update the value every so often (making it a random number).

I want to use that random number to display a quote from collection named 'texts'. Every quote's docname (id) is a stringified number, so I can use the value from num to get a quote. From what I can tell, it should be working, however, when I try to load the page that displays the quote, the console shows the number generating multiple times (usually 3-4, but sometimes more), the text updates every time it updates, and then it finally settles on a quote (but usually it's not even corresponding to the number from the random collection).

I have a feeling it has something to do with useState. I had a really hard time figuring out how to even display the data from Firestore, as it would give me an error saying I can't have a component can't return an object. Please advise on how I can fix this. I do have it currently deployed but the random number is set to update once a day. You'll be able to see how the quote changes before it settles on one (currently there are only 2 quotes in the database).

https://confidence-text-179ac.web.app/daily

Here's what I have:

import React, { useState } from 'react';
import firebaseConfig from './Config'
import firebase from "firebase/app";
import "firebase/firestore";

firebase.initializeApp(firebaseConfig);
const db = firebase.firestore();

const ConfidenceTexts = () => {
    const [text,setText] = useState("")
    const [num,setNum] = useState(1)

    const number = db.collection("random").doc('num');

    number.get().then((doc) => {
        setNum(doc.data().num)
    });

    const docRef = db.collection("texts").doc(num);

    docRef.get().then((doc) => {
        setText(doc.data().text)
    });

    return (
        <div>
            {text}
        </div>
    )
};

export default ConfidenceTexts;
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Cat
  • 65
  • 1
  • 6

1 Answers1

2

Every time you set state (update the state) your component is rerendering, and you get requests are being made again. Put your requests in a use effect with an empty conditional array so that the requests are only made on the first render.

useEffect(() => {
        number.get().then((doc) => {
            setNum(doc.data().num)
        });

        docRef.get().then((doc) => {
            setText(doc.data().text)
        });
    }, [])

If you want useEffect to run ONLY on the first render of the component, don't pass anything into your dependency array:

useEffect(() => {}, [])

If you want useEffect to run on EVERY render, use this (no dependency array):

useEffect(() => {})

If you want useEffect to run on the first render of the component, AND on state(s) changes, pass dependency states into the array:

useEffect(() => {}, [state, anotherState])

If you are trying to avoid useEffect rendering on the first render, you need to use a UseRef hook. This post will tell you how to go about doing this.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Noah Gwynn
  • 256
  • 2
  • 12
  • Now I'm getting an error saying a.indexOf is not a function – Cat Apr 24 '21 at 01:29
  • You also have an issue with trying to assign setState to a state in an unmounted component. You will need to add cleanup callbacks. Here is a good post for that issue: https://stackoverflow.com/questions/53949393/cant-perform-a-react-state-update-on-an-unmounted-component?answertab=active#tab-top – Noah Gwynn Apr 24 '21 at 01:34