Home > OS >  Can't properly render out Firebase data
Can't properly render out Firebase data

Time:07-23

I'm trying to render out a nested array of objects from my Firebase db. The code for adding the objects into the array works perfectly, but the rendering of the objects doesn't. This is the code for it:

//useStates
    const [newTodos, setNewTodos] = useState([]);
    const [user, setUser] = useState({});

    useEffect(() => {
        onAuthStateChanged(auth, (currentUser) => {
            setUser(currentUser);
        });

    }, [])

    useEffect(() => {
        //get the db user's todos and display them
        const getTodos = async () => {
            const userDoc = doc(db, "users", user.uid);
            const docSnap = await getDoc(userDoc);
            const todoList = docSnap.data().todos;
            setNewTodos(todoList);
        }
        getTodos();
    }, [])

It gives me this error message:

index.esm2017.js:1020 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'indexOf') at ht.fromString (index.esm2017.js:1020:1) at Da (index.esm2017.js:16739:1) at getTodos (TodoList.js:89:1) at TodoList.js:95:1 at commitHookEffectListMount (react-dom.development.js:23150:1) at commitPassiveMountOnFiber (react-dom.development.js:24926:1) at commitPassiveMountEffects_complete (react-dom.development.js:24891:1) at commitPassiveMountEffects_begin (react-dom.development.js:24878:1) at commitPassiveMountEffects (react-dom.development.js:24866:1) at flushPassiveEffectsImpl (react-dom.development.js:27039:1)

Line 89 is: const userDoc = doc(db, "users", user.uid);

Line 95 is: getTodos();

It worked kind of when I didn't wrap the getTodos function in the useEffect, but it breakes when I log in with another user since I render individual todos for each user.

It also kind of worked when I put the getTodos in a onLoad in this code (I had to "hack" this part for it to work, but it spat out the same error I have now):

if (newTodos.length == 0) {
        return (
            <div className="no-todos" onl oad={getTodos}>
                <Nav />
                <img id="hero-img" src={todopic} alt="todopic" />
                <Typography variant="h4">You are all done!</Typography>
            </div>
        )
        //if you have items render this
}else{...}

Edit

I put user in the dependency array of the useEffect and it works, but I still get a similar message.

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'indexOf') at ht.fromString (index.esm2017.js:1020:1) at Da (index.esm2017.js:16739:1) at getTodos (TodoList.js:89:1) at TodoList.js:94:1 at commitHookEffectListMount (react-dom.development.js:23150:1) at commitPassiveMountOnFiber (react-dom.development.js:24926:1) at commitPassiveMountEffects_complete (react-dom.development.js:24891:1) at commitPassiveMountEffects_begin (react-dom.development.js:24878:1) at commitPassiveMountEffects (react-dom.development.js:24866:1) at flushPassiveEffectsImpl (react-dom.development.js:27039:1)

Line 94: getTodos in the useEffect

I also don't get any problems when switching between the users.

CodePudding user response:

Your useEffect that calls getTodos is called on the first render, and on the first render your user object is equal to {}. So when your getTodos is trying to get user.uid it gets undefined, and looks like this undefined gets handled somehow inside doc function which leads to your error. The fix is pretty simple:

useEffect(() => {
  // due to user can be {} in your case
  if (!user || !user.uid) return; 

  const getTodos = async () => {
    const userDoc = doc(db, "users", user.uid);
    const docSnap = await getDoc(userDoc);
    const todoList = docSnap.data().todos; 
    
    // in case todoList is undefined - newTodos will still be an array
    // if todos is somehow not an array in firestore - that will not help btw.
    setNewTodos(todoList || []); 
  };
  getTodos();
}, [user]); // add user here to trigger useEffect when user object changed

  • Related