Firestore document not deleted - reactjs

I'm trying to delete a doc from Firestore, I don't get an error but the document is still in the database: simply as that, it keeps on being in the collection it belongs to.
The cloud function is:
exports.countdowns_crud = functions.https.onRequest((request, response) => {
var req = request;
var res = response;
if (request.method === 'DELETE') {
const countdownId = request.path.split('/')[1];
const deleteOperation = db.DeleteCountdown(countdownId);
if (!deleteOperation) {
console.log('Delete operation result: ', deleteOperation);
cors(req, res, () => {
res.status(204).send("DELETED");
});
}
else {
console.error(addOperation);
cors(req, res, () => {
res.status(500).send("INTERNAL SERVER ERROR");
});
};
return;
}
cors(req, res, () => {
res.status(405).send("NOT ALLOWED");
return;
});
})
The DeleteCountdown function is in another module:
module.exports = {
DeleteCountdown: (countdownId) => {
const countdownsCollection = app.firestore.collection('countdowns');
countdownsCollection.doc(countdownId).delete()
.then((res) => {
console.log('Result: ', res);
return null;
})
.catch((e) => {
console.error(`unable to delete the countdown ${countdowmnId}: ${e}`);
return e;
});
}
}
This is the logic in a google cloud function, which it's correctly invoked by my react app upon deletion. The passed id is correct, no error is returned, but the doc keeps on living in the collection.

I had the same problem, no error and null returned (exactly the same when it works) because I forgot to set the rules to allow writes (or specifically deletions) directly in the Firebase console or by the firestore.rules files

Related

trouble with async reucrsion of directories , with file system access api in react js

This code is designed to recursively iterate through a selected directory using the file system access api , and sent it via axios post request.
I have an encountered 2 problems :
I am struggling to find the right way to to enter subdirectories (now it only works for a directory with only files and no subDirs)
as you can see , i set a timeout before the post request , for some reason I cant identify , the promise in savedOCS function , probably resolves before it should.
I have the following code :
async uploadDirectory () {
const directoryHandle = await window.showDirectoryPicker();
const t0 = performance.now();
console.log(`t0 ${t0}`);
this.setState({chosenDirectory: directoryHandle.name} , ()=> {
console.log(this.state.chosenDirectory);
});
await this.handleDirectoryEntry(directoryHandle);
const t4 = performance.now();
console.log(`t4 ${t4}`);
setTimeout(() => {
this.axios.post(
'/DirectoryTransfer', {
directory: this.state.chosenDirectory,
directoryFiles: this.state.directoryFiles
}
).then((resData) => {
// this.fetchRemoteFileSystem();
const t5 = performance.now();
console.log(`t5 ${t5}`);
}).catch((error) => {
console.log(error)
})
}, 5000);
}
async handleDirectoryEntry(directoryHandle,subdir) {
let fileEntries = [];
console.log(directoryHandle);
for await (const entry of directoryHandle.values()) {
console.log(entry);
if(entry.kind === "file" && subdir === '') {
fileEntries.push(await entry.getFile());
}
}
console.log(fileEntries);
await this.saveDocs(fileEntries);
}
saveDocs = async (files) => {
const filePromises = files.map((file) => {
return new Promise ((resolve ,reject)=> {
const fileReader = new FileReader();
fileReader.onload = async ()=> {
try {
let directoryFiles = this.state.directoryFiles || [];
console.log('before setState: ', directoryFiles)
let response = false;
const t2 = performance.now();
console.log(`t2 ${t2}`)
await this.setState(
(prevState) => ({
directoryFiles: [...prevState.directoryFiles, { name: file.name, data: fileReader.result }]
}),
() => {
response = true;
console.log("after setState: ", this.state.directoryFiles);
const t3 = performance.now();
console.log(`t3 ${t3}`)
}
);
resolve(response);
} catch(err) {
reject(err)
}
}
fileReader.onerror = (err) => {
reject(err);
}
fileReader.readAsText(file);
})
})
const fileInfos = await Promise.all(filePromises);
return fileInfos;
}
i tried to find a way to iterate subDirs using recursion , and to async read files inside a directory.
current results :
the code reads the files fine.
without the timeout it sends a post request with an empty array of files.
doesn't have an implementation for subDirs.

Suddenly I can't make a GET query to Mongo DB without error code

everyone. I've been getting the error below since today. So far everything had always worked wonderfully. I haven't changed anything in the function either. I use mongoose within express/react.
Thank you very much
export const allRequestedArticels = async (req, res, next) => {
try {
const user = await User.findById(req.user.id);
const requestedArticel = user.requested;
if (requestedArticel.length) {
const list = await Promise.all(
requestedArticel.map(async (reqId) => {
return await Articel.find({ _id: reqId });
})
);
return res
.status(200)
.json(list.flat().sort((a, b) => b.createdAt - a.createdAt));
} else {
return res
.status(403)
.json("Sie haben bisher noch keine Artikel angefragt");
}
} catch (error) {
return next(createError(403, error));
}
};
{"success":false,"status":500,"message":"Cast to ObjectId failed for value "requests" (type string) at path "_id" for model "User""}

Compare SSE local and Global versions when using eventSource and Server Sent Events

Am using server sent events in an express server like this;
const sendEventDashboard = async (req, res) => {
try {
const orders = await Order.find({ agent_id: req.params.id })
.populate("agent_id")
.sort({ _id: -1 });
res.writeHead(200, {
"Cache-Control": "no-cache",
"Content-Type": "text/event-stream",
Connection: "keep-alive",
});
const sseId = new Date().toDateString();
const intervalId = setInterval(() => {
writeEvent(res, sseId, JSON.stringify(orders));
}, SEND_INTERVAL);
res.on("close", () => {
clearInterval(intervalId);
res.end();
// console.log("Client closed connection browser");
});
} catch (error) {
console.log(error);
}
};
export const getOrdersStreamDashboard = async (req, res) => {
if (req.headers.accept === "text/event-stream") {
sendEventDashboard(req, res);
} else {
res.json({ message: "Okay" });
}
};
and this is how i use it in a react app using a useEffect hook;
useEffect(() => {
const es = new EventSource(
`${process.env.REACT_APP_SERVER_URL}/weborders/${agentId}/stream_dashboard`
);
es.addEventListener("open", () => {
console.log("Dashboard stream opened!");
});
es.addEventListener("message", (e) => {
const data = JSON.parse(e.data);
setTrackOrderCount(data);
});
return () => {
// es.removeAllEventListeners();
es.close();
es.removeEventListener("message", (e) => {
const data = JSON.parse(e.data);
setTrackOrderCount(data);
});
};
}, [trackOrderCount]);
Everything runs as desired apart from event source always running until when the app/browser crushes. I get no error when it stops running and have to refresh for it to start again. This happens like after 10mins of inactivity or being on that same page for a long duration. Is there a way I can only run sse only when the state in the server is different from that of the client because i think the browser crushes because server sent events continuously run even when there's no event. I tried to remove the dependency array [trackOrderCount] in the useEffect and the setInterval in the server but that didn't solve the issue.
The solution might be in comparing the local and global versions before the event is sent but i've failed to figure out where to put that logic! I the browser's console, this is what i get;
and this will run for sometime then crush!

How to get a single document from firestore?

According to the documentation from firebase you can get a document very simply by using get()
But for some reason in my code it always displays that there's no such document, even though it does exist, this is what I'm doing:
useEffect(() => {
console.log(user, "This is the user UID:"+user.uid)
const userDoc = db.collection('usuarios').doc(user.uid);
const doc = userDoc.get();
if (!doc.exists) {
console.log('No such document!');
}
else {
userDoc
.onSnapshot(snapshot => {
const tempData = [];
snapshot.forEach((doc) => {
const data = doc.data();
tempData.push(data);
});
setUserData(tempData);
})
}
}, [user]);
This is what the console.log() shows:
This is how it looks in firebase:
const doc = userDoc.get();
if (!doc.exists) {
.get returns a promise, so you're checking the .exists property on a promise, which is undefined. You will need to wait for that promise to resolve, either with .then:
userDoc.get().then(doc => {
if (!doc.exists) {
// etc
}
});
Or by putting your code in an async function and awaiting the promise:
const doc = await userDoc.get();
if (!doc.exists) {
// etc
}
If you're using the firebase 8 web version, the userDoc.get() returns a promise, not the document:
userDoc.get().then((doc) => {
if (!doc.exists) {
console.log('No such document!');
} else {
const tempData = [];
const data = doc.data();
tempData.push(data);
setUserData(tempData)
console.log('it worked')
}
}).catch((error) => {
console.log("Error getting document:", error);
});
You can get more info about promises in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises.
In your code you are using the get method to fetch user data and get doesn't provide a snapshot. also, you missed that get() will return a promise so you have to handle using async-await or .then etc.
useEffect(() => {
console.log(user, "This is the user UID:"+user.uid);
getUser(user.uid).then(userData => {
setUserData(userData);
});
}, [user]);
const getUser = async (id) => {
try {
const user = await db.collection('usuarios').doc(id).get();
const userData = user.data();
return userData;
} catch (err){
console.log('Error during get user, No such document!');
return false;
}

Multiple nested axios calls don't resolve as expected

As described in comments between my code snippet, the asynchronicity is not working as expected. For each id, an object/item should return but it only returns one item since my async await isn't implemented properly. What could be a possible workaround?
Thanks in advance
useEffect(() => {
axios.get('url-here').then((res) => {
res.data.favProperties?.map((el) => {
console.log(el) // this returns multitple id's of saved/liked items
axios.get('url-here').then(async (r) => {
if (r.data) {
console.log(r.data) // Problem starts here
// This returns the full object of the liked items
// But only one object is returned, not every object for which an id was stored
await storageRef
.child(r.data.firebaseRef + '/' + r.data.images[0])
.getDownloadURL()
.then((url) => {
// Here i need to fetch the image for each object
console.log(url)
})
.catch((err) => console.log(err))
}
})
})
})
}, [])
I think breaking down your operations into functions will prevent this Promise Hell. I would recommend using async await for these kinda operations. Also I was confused about the last part of console logging the download URL, by my guess you're trying to save all the download URLs for these liked items in an array.
useEffect(() => {
firstFunction();
}, []);
const firstFunction = async () => {
const { data } = await axios.get("url-here");
const favProperties = data.favProperties;
const fetchedUrls = await Promise.all(
favProperties?.map(async (el) => (
await secondFunction(el.id) /** use el to pass some ID */
))
);
};
const secondFunction = async (someId) => {
/** your second URL must point to some ID (or some parameters) specific API otherwise
running same op in a loop without variations doesn't make any sense */
const { data } = await axios.get(`some-other-url/${someId}`);
if (data) {
console.log(data);
const fetchedUrl = await storageThing(data);
return fetchedUrl;
}
};
const storageThing = async ({ firebaseRef, images }) => {
try {
const downloadURL = await storageRef
.child(firebaseRef + "/" + images[0])
.getDownloadURL();
console.log(downloadURL);
return downloadURL;
} catch (error) {
console.log(error);
return '';
}
};

Resources