\n
firestore screenshot after refreshing app (updating item description works)\n
I figured it out...
\nThe id of newly created item which I am using to update the doc is a number. But the id on firestore is a string, not a number.
\nchanging the handleSubmit callback from .doc(editItem.id)
to this fixed it:
.doc(`${editItem.id}`)\n
\n","author":{"@type":"Person","name":"TribeOfOne"},"upvoteCount":1}}}Reputation: 173
I have a react app which allows creation of lists for logged in users (groceries, todo, etc) and stores data on firebase.firestore. It's still in development using localhost. If I create a new list, add items to it and immediately edit the item description, I get a TypeError and item description doesn't update in app or firestore. If I pick a different list to display, then click back to new list or refresh the browser before I edit the item description, everything works fine. It just doesn't work if I specifically create new list, add items to it, and immediately try to edit the item description, even though I check firestore before submitting change and the new list and new items are shown to exist.
Any idea why the await checkDoc in the handleSubmit isn't working unless I refresh app in browser first?
I included firestore screenshots before and after app refresh in case it matters. They seem identical to me.
Github repo is branch edit-item github repo
error showing in console when I update item description without refreshing:
TypeError: u.indexOf is not a function
at Function.e.ot (prebuilt-67479dbf-318e5a2c.js:878)
at Bs (prebuilt-67479dbf-318e5a2c.js:14560)
at e.doc (prebuilt-67479dbf-318e5a2c.js:18281)
at handleSubmit (EditItem.js:32)
at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
at invokeGuardedCallback (react-dom.development.js:4056)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:4070)
at executeDispatch (react-dom.development.js:8243)
at processDispatchQueueItemsInOrder (react-dom.development.js:8275)
at processDispatchQueue (react-dom.development.js:8288)
at dispatchEventsForPlugins (react-dom.development.js:8299)
at react-dom.development.js:8508
at batchedEventUpdates$1 (react-dom.development.js:22396)
at batchedEventUpdates (react-dom.development.js:3745)
at dispatchEventForPluginEventSystem (react-dom.development.js:8507)
at attemptToDispatchEvent (react-dom.development.js:6005)
at dispatchEvent (react-dom.development.js:5924)
at unstable_runWithPriority (scheduler.development.js:646)
at runWithPriority$1 (react-dom.development.js:11276)
at discreteUpdates$1 (react-dom.development.js:22413)
at discreteUpdates (react-dom.development.js:3756)
at dispatchDiscreteEvent (react-dom.development.js:5889)
EditItem componant with handleSubmit function giving error unless I refresh first:
import React, { useState } from 'react';
import { db } from '../../hooks/useAuth';
import {
Button,
Input,
Center,
FormControl,
Flex,
Heading,
} from '@chakra-ui/react';
const EditItem = ({
user,
items,
setItems,
setEditItem,
currentList,
editItem,
themeObj,
}) => {
const checkDoc = db.collection('users').doc(user.uid);
const [newDesc, setNewDesc] = useState('');
const handleSubmit = async e => {
e.preventDefault();
try {
console.log(editItem);
console.log(newDesc);
console.log(currentList);
console.log(editItem.id);
await checkDoc
.collection(currentList)
.doc(editItem.id)
.update({ desc: newDesc });
const editedList = items.map(item =>
item.id === editItem.id ? { ...item, desc: newDesc } : item
);
setItems(editedList);
console.log(editedList);
setNewDesc(`${editItem.desc}`);
setEditItem(null);
} catch (err) {
console.log(err);
} finally {
}
};
return (
<Flex w="100%" grow="1" direction="column" p={6}>
<Center
mb="1rem"
borderRadius="lg"
p={3}
bg={themeObj.bg}
color={themeObj.color}
>
<Heading size="md">Edit Item Description</Heading>
</Center>
<Center
mb="1rem"
borderRadius="lg"
p={3}
bg={themeObj.bgItem}
color={themeObj.colorItem}
>
{newDesc.length ? newDesc : editItem.desc}
</Center>
<form
label="New Item Description"
onSubmit={handleSubmit}
style={{ width: '100%' }}
>
<FormControl>
<Input
required
variant="outline"
autoFocus
// ref={inputRef}
type="text"
id="newDesc"
placeholder="New Item Description"
required
value={newDesc}
onChange={e => setNewDesc(e.target.value)}
/>
<Button
variant="solid"
mt={4}
type="submit"
aria-label="Rename List"
color="white"
_hover={{
background: `${themeObj.checkScheme}`,
}}
bg="black"
>
Update
</Button>
<Button
variant="solid"
mt={4}
type="button"
onClick={() => {
setEditItem(null);
setNewDesc(`${editItem.desc}`);
}}
aria-label="cancel"
color="white"
_hover={{
background: `${themeObj.checkScheme}`,
}}
bg="red"
>
Cancel
</Button>
</FormControl>
</form>
</Flex>
);
};
export default EditItem;
Dashboard component (parent to EditItem):
import React, { useState, useEffect } from 'react';
import { InputGroup, Stack, Flex } from '@chakra-ui/react';
import firebase from 'firebase/app';
import EditItem from '../iList/EditItem';
import Loader from '../iList/Loader';
import AddItem from '../iList/AddItem';
import SearchItem from '../iList/SearchItem';
import Content from '../iList/Content';
import Footer from '../iList/Footer';
import { useAuth, db } from '../../hooks/useAuth';
import 'firebase/firestore';
const Dashboard = ({
setAppTheme,
loaderLoading,
setLoaderLoading,
setIsLoading,
isLoading,
fetchError,
setFetchError,
themeObj,
currentList,
setCurrentList,
}) => {
console.log(currentList);
const { user } = useAuth();
const [items, setItems] = useState([]);
const [search, setSearch] = useState('');
const [editItem, setEditItem] = useState(null);
const [newItem, setNewItem] = useState('');
const checkDoc = db.collection('users').doc(user.uid);
const itemsCollection = db
.collection('users')
.doc(user.uid)
.collection(currentList);
useEffect(() => {
checkIfInitialized();
const getUserPrefs = async () => {
try {
const userList = await checkDoc.get();
setCurrentList(userList.data().currentlist);
setAppTheme(userList.data().currenttheme);
setFetchError(null);
} catch (err) {
setFetchError(err.message);
console.log(err.message);
} finally {
setLoaderLoading(false);
setIsLoading(false);
}
};
getUserPrefs();
}, []);
useEffect(() => {
const getItems = async () => {
try {
const data = await itemsCollection.get();
const listItems = data.docs.map(doc => ({
...doc.data(),
id: doc.id,
}));
setItems(listItems);
setFetchError(null);
} catch (err) {
setFetchError(err.message);
} finally {
setLoaderLoading(false);
}
};
getItems();
}, [currentList]);
const addItem = async item => {
const id = items.length ? Number(items[items.length - 1].id) + 1 : 1;
console.log(id);
const newItemDate = new Date();
const dateStr = `${
newItemDate.getMonth() + 1
}/${newItemDate.getDate()}/${newItemDate.getFullYear()}`;
const myNewItem = {
id: id,
checked: false,
desc: item,
date: dateStr,
};
const listItems = [...items, myNewItem];
setItems(listItems);
const addedDoc = db
.collection('users')
.doc(user.uid)
.collection(currentList)
.doc(`${myNewItem.id}`);
await addedDoc
.set({ desc: myNewItem.desc, checked: false, date: dateStr })
.then(() => {
console.log('Document successfully written!');
})
.catch(error => {
console.error('Error writing document: ', error);
});
};
const handleCheck = async id => {
const listItems = items.map(item =>
item.id === id ? { ...item, checked: !item.checked } : item
);
setItems(listItems);
const myItem = items.filter(item => item.id === id);
console.log(myItem);
const updatedDoc = db
.collection('users')
.doc(user.uid)
.collection(currentList)
.doc(`${id}`);
console.log('here');
await updatedDoc
.update({
checked: !myItem[0].checked,
})
.then(() => {
console.log('Document successfully updated!');
})
.catch(error => {
// The document probably doesn't exist.
console.error('Error updating document: ', error);
});
};
const handleDelete = async id => {
const listItems = items.filter(item => item.id !== id);
setItems(listItems);
const deletedDoc = db
.collection('users')
.doc(user.uid)
.collection(currentList)
.doc(`${id}`);
await deletedDoc
.delete()
.then(() => {
console.log('Document successfully deleted!');
})
.catch(error => {
console.error('Error removing document: ', error);
});
};
const handleSubmit = e => {
e.preventDefault();
if (!newItem) return;
addItem(newItem);
setNewItem('');
};
const checkIfInitialized = () => {
const docRef = db.collection('users').doc(user.uid);
docRef
.get()
.then(doc => {
if (doc.exists) {
console.log('Document data:', doc.data());
} else {
// doc.data() will be undefined in this case
console.log('No such document!');
initializeUserDb();
}
})
.catch(error => {
console.log('Error getting document:', error);
});
};
const initializeUserDb = async () => {
const firstEntry = db.collection('users').doc(user.uid);
await firstEntry
.set({
currentlist: currentList,
mylists: firebase.firestore.FieldValue.arrayUnion('My List'),
currenttheme: 'default',
email: user.email,
})
.then(() => {
console.log('currentlist successfully written!');
})
.catch(error => {
console.error('Error writing document: ', error);
});
};
return (
<>
{editItem && (
<EditItem
items={items}
setItems={setItems}
currentList={currentList}
user={user}
editItem={editItem}
setEditItem={setEditItem}
themeObj={themeObj}
/>
)}
{!editItem && (
<>
<Stack mb={3} w="100%" p={3}>
<InputGroup>
<AddItem
themeObj={themeObj}
newItem={newItem}
setNewItem={setNewItem}
handleSubmit={handleSubmit}
/>
</InputGroup>
<InputGroup>
<SearchItem
themeObj={themeObj}
search={search}
setSearch={setSearch}
/>
</InputGroup>
</Stack>
<Flex
w="100%"
flexDirection="column"
flexGrow="1"
justifyContent="flex-start"
align-items="center"
overflowY="auto"
>
{(isLoading || loaderLoading) && <Loader />}
{fetchError && (
<p style={{ color: 'red' }}>{`Error: ${fetchError}`}</p>
)}
{!fetchError && !loaderLoading && !isLoading && (
<Content
setEditItem={setEditItem}
themeObj={themeObj}
items={items.filter(item =>
item.desc.toLowerCase().includes(search.toLowerCase())
)}
handleDelete={handleDelete}
handleCheck={handleCheck}
/>
)}
</Flex>
</>
)}
<Footer bg={themeObj.bg} color={themeObj.color} length={items.length} />
</>
);
};
export default Dashboard;
firestore screenshot before refreshing app (I just created "test list" and two items and updating item desc doesn't work)
firestore screenshot after refreshing app (updating item description works)
Upvotes: 1
Views: 140
Reputation: 173
I figured it out...
The id of newly created item which I am using to update the doc is a number. But the id on firestore is a string, not a number.
changing the handleSubmit callback from .doc(editItem.id)
to this fixed it:
.doc(`${editItem.id}`)
Upvotes: 1