Hi I just started learning how to use Firestore, and I’m doing a CRUD app to help me with that. I’m trying to create a projects that’s basically a collection -> document -> subcolletion -> document.
but I get an error: TypeError: Cannot read properties of undefined (reading ‘indexOf’)
this is just dummy text code for me to try things out first.
firebase.js
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
import { getFirestore } from 'firebase/firestore'
// TODO: Replace the following with your app's Firebase project configuration
const firebaseConfig = {
apiKey: process.env.NEXT_PUBLIC_APIKEY,
authDomain: process.env.NEXT_PUBLIC_AUTHDOMAIN,
projectId: process.env.NEXT_PUBLIC_PROJECTID,
storageBucket: process.env.NEXT_PUBLIC_STORAGEBUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_MESSAGINGSENDERID,
appId: process.env.NEXT_PUBLIC_APPID,
measurementId: process.env.NEXT_PUBLIC_MEASUREMENTID
}
const app = initializeApp(firebaseConfig)
export const auth = getAuth(app)
export const db = getFirestore(app)
AuthContext.js
import React, { useContext, useState, useEffect, useRef} from 'react'
import { auth, db } from '../firebase'
import { signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut, onAuthStateChanged, updateProfile } from 'firebase/auth'
import { addDoc, doc, setDoc, getDoc, collection } from 'firebase/firestore'
const AuthContext = React.createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState(null)
const [loading, setLoading] = useState(true)
const projectsCollection = "projects";
function signup(email, password) {
return createUserWithEmailAndPassword(auth, email, password)
}
function setuserName (username) {
return updateProfile(auth.currentUser, { displayName: username })
}
function login(email, password) {
return signInWithEmailAndPassword(auth, email, password)
}
function logout() {
return signOut(auth)
}
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
///////////////////////////////////////////////////
function createProject(projectName) {
const projectRef = addDoc(collection(db, projectsCollection), {
name: projectName
});
const DocRef = doc(db, projectsCollection , projectRef.uid)
const teamColRef = collection(DocRef,"team")
addDoc(teamColRef, {
email: "[email protected]"
})
const tasksColRef = collection(DocRef,"tasks")
addDoc(tasksColRef, {
title: "lets go do something",
status: "doing",
assignedTo: "[email protected]"
})
}
const value = {
currentUser,
login,
signup,
logout,
setuserName,
createProject,
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
)
}
ProjectAssing.js
import React, {useState, useEffect} from 'react';
import Router from 'next/router';
import { useAuth } from '@/context/AuthContext';
export default function ProjectAssign({ projectName, projectTasks, projectTeam}) {
const [selectedMember, setSelectedMember] = useState("")
const [selectedTask, setselectedTask] = useState("")
const [allTasks, setallTasks] = useState([...projectTasks])
const [assignments, setAssignments] = useState([])
const {createProject} = useAuth()
useEffect(() => {
if (selectedMember && selectedTask) {
const foundIndex = assignments.findIndex((assignment) => assignment.member === selectedMember)
if (foundIndex === -1) {
setAssignments([
...assignments,
{ member: selectedMember, tasks: [selectedTask] },
]);
} else {
setAssignments([
...assignments.slice(0, foundIndex),
{
...assignments[foundIndex],
tasks: [...assignments[foundIndex].tasks, selectedTask],
},
...assignments.slice(foundIndex + 1),
]);
}
setallTasks(allTasks.filter(task => task !== selectedTask));
setselectedTask("")
setSelectedMember("")
}
}, [selectedMember, selectedTask, assignments]);
const handleCreateProject = async () => {
try {
createProject(projectName)
} catch (error) {
console.log(error)
}
}
return (
<div className='w-full min-h-screen p-5 text-white bg-black'>
<i
onClick={() => Router.push("/UserDashboard")}
className=' absolute cursor-pointer fa-solid fa-xmark text-white text-5xl m-10 right-0 top-0 duration-300 hover:scale-110 rounded-xl hover:text-cyan-400'></i>
<div className='flex items-center flex-col'>
<h1 className="py-20 font-extrabold text-4xl">{projectName}</h1>
<div className=' flex flex-row'>
<div className="flex-1">
<h1 className='text-center text-lg font-medium'>Team</h1>
<div>
{
projectTeam.map((member, index) => (
<div
key={index}
className={`flex cursor-pointer items-center p-2 m-2 border-solid rounded-md border-white border-2 duration-300 hover:scale-110 ${selectedMember === member
? ' border-green-400'
: ''}`}
onClick={() => setSelectedMember(member)}>
<p
className={` text-sm font-normal ${selectedMember === member
? ' text-green-400'
: 'text-white'}`}>{member}</p>
</div>
))
}
</div>
</div>
<div className="flex-1">
<h1 className='text-center text-lg font-medium'>Tasks</h1>
<div>
{
allTasks.map((task, index) => (
<div
key={index}
className={`flex cursor-pointer items-center p-2 m-2 border-solid rounded-md border-white border-2 duration-300 hover:scale-110 ${selectedTask === task
? ' border-green-400'
: ''}`}
onClick={() => setselectedTask(task)}>
<p
className={` text-sm font-normal ${selectedTask === task
? ' text-green-400'
: 'text-white'}`}>{task}</p>
</div>
))
}
</div>
</div>
</div>
</div>
<div className='w-full text-center text-white font-extrabold text-2xl p-5 '>
<h1> Review: </h1>
</div>
<div className=' mb-20 text-white grid grid-cols-1 gap-4 mx-10 mt-10 sm:grid-cols-2 md:grid-cols-4'>
{
assignments.map(( {member, tasks}) => (
<div key={member} className='flex flex-col border-white border-2 rounded-md p-2 '>
<h1 className='text-center text-lg font-medium'>{member}</h1>
{tasks.map((task, index) => (
<div key={index} className=" flex justify-between cursor-pointer p-2 m-2 border-solid rounded-md border-white border-2 duration-300 hover:scale-110 ">
<p className="text-white text-sm font-normal mr-4">{task}</p>
<i
className=" fa-solid fa-trash text-white text-xl duration-300 hover:scale-110 hover:text-red-400 "></i>
</div>
))}
</div>
))}
</div>
<i
onClick={handleCreateProject}
className='fixed right-0 bottom-0 cursor-pointer text-5xl m-10 fa-solid fa-circle-check text-white duration-300 hover:scale-110 rounded-xl hover:text-cyan-400'></i>
</div>
);
}
I’m able to create the document inside projects collection, but not the subcollection…
2
Answers
All I needed to do was to change the .uid to .id
const docRef = doc(db, "projects" , projectRef.id)
This error message typically means that one of the values you’re passing to the Firestore API is
undefined
.We can’t say which one that is from what you shared so far, but if you
console.log
each variable right before you call Firestore with it, it should be pretty easy to figure out which one isundefined
.