I have been trying for months to figure out how to display a firestore timestamp in react.
In December 2019, the solution I accepted on this post worked. It no longer works. I'm back to stuck.
I have a firebase.js helper to record dates with:
class Firebase {
constructor() {
app.initializeApp(config)
this.firestore = app.firestore();
this.auth = app.auth();
this.serverTimestamp = app.firestore.FieldValue.serverTimestamp;
}
I use that helper in forms to record the date an entry is created like so:
await Firebase.firestore.collection("blog").doc().set({
title: values.title,
createdAt: Firebase.serverTimestamp()
That correctly saves a date into the firestore document that looks like this:
When I hover over the date, it shows 'timestamp'. I am able to order the data returned from firestore by reference to the createdAt date - so it's curious that the timestamp can be used to sort the documents but cannot be used to print the date on the screen.
When it then comes to outputting the date, I am back to getting all the same errors I reported in the previous post - but the solution that worked in December, no longer works. I have seen a discussion in the firebase slack channel that a recent release of firebase has had some unintended consequences - is there any way to check if broken timestamps is one of them?
When I try:
{currentPost.createdAt.toDate().toISOString()}
TypeError: Cannot read property 'toDate' of undefined
When I try:
{currentPost.createdAt.toDate()}
TypeError: Cannot read property 'toDate' of undefined
When I try:
{new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
TypeError: Cannot read property 'seconds' of undefined
When I try (I know this won't work but just trying to find insights that might help solve this problem):
{currentPost.createdAt}
Error: Objects are not valid as a React child (found: object with keys
{seconds, nanoseconds}). If you meant to render a collection of
children, use an array instead.
I have seen some posts which say the date is undefined because the call on firebase hasn't returned a value yet, but when I console.log the whole currentPost, I get a value for created At, which is:
createdAt: t seconds: 1586495818 nanoseconds: 888000000
The part of this that looks suspicious is the "t". Does it represent something that I'm supposed to do something with in order to access the timestamp? Does anyone know how to investigate what the 't' represents?
I have seen this post and this post, and note that each of the answers to it suggest that the .toDate() extension should help to convert a firestore timestamp to something that can be output. None of those solutions work here.
Has anyone figured out a current solution that allows to both save and output a date from firestore?
Strange - I don't understand why or how this works, but it does.
I changed the useEffect to be async - as follows.
function ReadBlogPost () {
const [loading, setLoading] = useState(true);
const [currentPost, setCurrentPost] = useState({});
let { slug } = useParams();
useEffect(() => {
const fetchData = async() => {
try {
const response = await Firebase.firestore
.collection("blog")
.doc(slug)
.get();
console.log('response', response);
let data = { title: 'not found' };
if (response.exists) {
data = response.data();
}
setCurrentPost(data);
setLoading(false);
} catch(err) {
console.error(err);
}
};
fetchData();
}, []);
Then in the render, I can use:
{!loading && new Date(currentPost.createdAt.seconds * 1000).toLocaleDateString("en-US")}
Fingers crossed this works for more than a few months.
I was facing the same problem. The solution is simple for me, You have to first check if the timestamp exists or not.
{data.time === undefined ? (
<div>Time is not defined</div>
) : (
<div> {data.time.toDate().toLocaleTimeString("en-US")}</div>
)}
After that, you can do whatever you want.
(Frist time answering any questions, If i made any mistake, please do tell)
This worked for me:
{data.timestamp.toDate().toLocaleTimeString("en-US")}
Related
I am trying to fetch data from a Supabase table called "profiles" with Next.js 13 and the app directory. I am trying to take advantage of the new next.js fetching methods, my code looks as follows:
export const revalidate = 0;
export default async function getData() {
const { data: profiles } = await supabase
.from("profiles")
.select("*")
.eq("is_host", true);
console.log(profiles);
return { profiles };
if (!profiles) {
return <p>No hosts found</p>
}
The problem is that this code seems to be wrapping the array returned from Supabase in an object.
The data returned looks like this:
{data:
[
{
"id":"feef56d9-cb61-4c4d-88c6-8a8d7c9493d9",
"updated_at":null,
"username":"username",
"full_name":"Full Name",
"avatar_url":"URL",
"website":null,
"is_host":true,
"bio":null,
"languages":6
}
]
}
When I use useState and useEffect instead, the data is returned as expected, and I can map through it.
Does anybody have an idea why, and how I can prevent that?
Thanks in advance.
I worked it out, through a subsequent error, which I as able to solve thanks to the question I asked here and the helpful hints I got from there.
return { profiles };
Returns the array inside an object.
By removing the {} I was able to fetch the array inside of it.
I have a problem while trying to update data in the firebase database with my react code.
Most probably my code syntax is not good, so can you help me in some way?
This is my code syntax:
const addNewData = async (e) => {
e.preventDefault();
let data = {
sifra:sifraRef.current.value,
naziv:nazivRef.current.value,
detalji_dijete:detaljiRef.current.value,
opis:opisRef.current.value,
broj_obroka:brojObrokaRef.current.value,
napomena:napomenaRef.current.value
}
const uuid = uid();
await updateDoc(collection(db, `namirnice/${uuid}`), data)
close();
}
All these examples I saw on youtube tutorials works...
I hope you can help me.
The updateDoc function is used to update an existing document. But since you call uuid(), you always get a new value and so you're trying to update a document that doesn't exist yet, which isn't possible.
To create a new document, use setDoc instead of updateDoc in your code.
Also see the Firebase documentation on setting a document
Iam trying to store a list of product ids in an array in database and retrieve the latest array.
this is my server side code
router.post("/scannedproducts",async(request,response)=>{
console.log(request.body)
const Scannedproducts = new scannedproducts({
ids:request.body
})
Scannedproducts.save()
console.log(Scannedproducts)
const getLatestProduct =await scannedproducts.find().sort({ createdAt: -1 }).limit(1) // 10 latest docs
console.log(getLatestProduct)
})
but it consolelogs an empty array of ids.
please help...
The mistake in your code is you should have used await while calling the save() method
Solution should be :
router.post("/scannedproducts",async(request,response)=>{
const Scannedproducts = new scannedproducts({
ids:req.body
})
await Scannedproducts.save()
console.log(Scannedproducts)
const getLatestProduct =await scannedproducts.find().sort({ createdAt:-1 }).limit(1) // 10 latest docs
console.log(getLatestProduct)
})
it would fix your issue,
But anyways You should have provided the scannedProducts model in your question, and assigning the whole request body object to a property is a bad practice. you should take an ids array as user input and store it in server
i would suggest you to write your code as:
router.post("/scannedproducts",async(request,response)=>{
const Scannedproducts = new scannedproducts({
ids:req.body.ids
})
await Scannedproducts.save()
console.log(Scannedproducts)
const getLatestProduct =await scannedproducts.find().sort({ createdAt:-1 }).limit(1) // 10 latest docs
console.log(getLatestProduct)
})
Thank you
thanks in advance!
In summary, I am using React's WYSIWYG rich text editor, and saving the text written in the editor to a MongoDB, data is sent to a server which does the insertion. My issue is that I am unable, after following recommended code, to retrieve the stored data back successfully to display it on my page. This is for a prospective blog post site.
Below I've provided all relevant code:
My Component which sends the data to the server to insert it into MongoDB, (not in order, only relevant code):
<Editor
editorState={editorState}
onEditorStateChange={handleEditorChange}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
/>
const Practice = () => {
const [editorState, setEditorState] = useState(
() => EditorState.createEmpty(),
);
const [convertedContent, setConvertedContent] = useState(null);
const handleEditorChange = (state) => {
setEditorState(state);
convertContentToRaw();
}
const convertContentToRaw = () => {
const contentState = editorState.getCurrentContent();
setEditorState(editorState: {convertToRaw(contentState)});
}
const stateToSend = JSON.stringify(editorState);
try {
const response = await axios.post('http://localhost:8080/api/insert', {
content: stateToSend
})
} catch(error) {
}
In MongoDB, I've initialized 1 column for storing the WYSIWYG data, I've initialized as an empty JS object:
const wysiwygtest = new mongoose.Schema({
content: {
type: {}
}
});
As a result, my data is inserted into MongoDB as such, with everything desired clearly in data type such as RGBA etc. correct me if I'm wrong but I believe Mongo uses BSON, a form of binary based JSON, so this looks doable for retrieval:
Lastly, the code which is not working correctly, the retrieval. For this, I have no interest just yet in placing the data back into the text editor. Rather, I'd like to display it on the page like a typical blog post. However, I'm unable to even log to the console as of yet.
I am parsing the data back to JSON using JSON.parse, converting JSON to JS object using createFromRaw and using EdiorState (even though I don't have the text editor in this component but this seems to be needed to convert the data fully..) to convert fully:
useEffect( async () => {
try {
const response = await axios.get('http://localhost:8080/api/query', {
_id: '60da9673b996f54d507dbfc5'
});
const content = response;
if(content) {
const convertedContent =
EditorState.createWithContent(convertFromRaw(JSON.parse(content)));
console.log('convertedContent - ', convertedContent);
}
console.log('response - ', content);
} catch(error) {
console.log('error!', error);
}
}, [])
My result for the past day and last night has been the following:
"SyntaxError: Unexpected token o in JSON at position 1" and so I'm unsure what I'm doing wrong in the data retrieval, and possibly even the insertion.
Any ideas? Thanks again!
Edit: For more reference, here is what the data looks like when output to the console without a JSON.stringify, this is the full tree of data. I can see all of the relevant data is there, but how do I convert this data and display it into a div or paragraph tag, for example?
More or less figured this out, see my solution below given the aforementioned implementation:
Firstly, I think my biggest mistake was using JSON.parse(); I did away with this with success. My guess as to why this does not work (even though I inserted into MongoDB as JSON) is because we ultimately need the draft-js.Editor Object to convert the data from the DB into an object type it can understand, in order to subsequently convert into HTML successfully, with all properties.
Below is the code with captions/descriptions:
Retrieve data (in useEffect before React component is rendered:
useEffect( async () => {
console.log('useeffect');
try {
const response = await axios.get('http://localhost:8080/api/query', {
_id: '60da9673b996f54d507dbfc5' //hard-coded id from DB for testing
});
const content = response.data; //get JSON data from MongoDB
if(content) {
const rawContent = convertFromRaw(content); //convert from JSON to contentstate understood by DraftJS, for EditorState obj to use
setEditorState(EditorState.createWithContent(rawContent)); //create EditorState based on JSON data from DB and set into component state
let currentContentAsHTML = draftToHtml(convertToRaw(editorState.getCurrentContent())); //create object which converts contentstate understood by DraftJS into a regular vanilla JS object, then take THAT and convert into HTML with "draftToHtml" function. Save that into our 2nd state titled "convertedContent" to be displayed on page for blog post
setConvertedContent(currentContentAsHTML);
}
} catch(error) {
console.log('error retrieving!', error);
} },[convertedContent]) //ensure dependency with with convertedContent state, DB/server calls take time...
In component render, return HTML which sets the innerHTML in the DOM using/passing the convertedContent state which we converted to proper HTML format in step 1.
return (
<div className="blog-container" dangerouslySetInnerHTML={createMarkup(convertedContent)}></div>
</div>
);
In step 2, we called a function entitled, "createMarkup"; here is that method. It essentially returns HTML object using the HTML converted data originally from our database. This is a bit vulnerable it terms of malicious users being able to intercept that HTML in the DOM, however, so we use a method, "purify" from "DOMPurify" class from 'isomorphic-dompurify" library. I'm using this instead of regular DOMPurify because I am using Next JS and NEXT runs on the server side as well, and DOMPurify only expects client side:
const createMarkup = (html) => {
return {
__html: DOMPurify.sanitize(html)
}
}
I've been trying to save data from my form in my MongoDB for some time.
I also get a response from the database.
See also: create object in mongo db api onclick sending form
Unfortunately there are not enough tutorials in my mother tongue and I don't seem to understand everything in English.
I've tried some of the documentation, but I always fail.
What is missing in my webhook function so that the form data can be stored?
exports = function(payload) {
const mongodb = context.services.get("mongodb-atlas");
const mycollection = mongodb.db("created_notifications").collection("dpvn_collection");
return mycollection.find({}).limit(10).toArray();
};
The Webhookfunction was totally wrong.
READ THE DOCUMENTATION FIRST
exports = function(payload, response) {
const mongodb = context.services.get("mongodb-atlas");
const requestLogs = mongodb.db("created_notifications").collection("dpvn_collection");
requestLogs.insertOne({
body: EJSON.parse(payload.body.text()),
query: payload.query
}).then(result => {
})
};