简体   繁体   中英

Next.js and Firebase keep getting serialization error when trying to read one doc

As the title says, I'm trying to build out a blog site and I have most of it done expect for clicking on a post stub to read the full post. I keep getting this error anytime I go to the post page.

Error: Error serializing .post returned from getServerSideProps in "/posts/[slug]". Reason: undefined cannot be serialized as JSON. Please use null or omit this value.

I've searched everywhere to try and figure out what I'm doing wrong but can't seem to find the right answer.

Here is by firebase code.

import {
  collection,
  getDocs,
  getFirestore,
  limit,
  onSnapshot,
  orderBy,
  query,
  doc,
  setDoc,
  getDoc,
} from "firebase/firestore";
import firebase from "firebase/app";
import { initializeApp, getApps, getApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
import { Timestamp, toJSON } from "firebase/firestore";
// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "AIzaSyAB4SbXl-I1TMoa31ybnCzmTASXjZFnMAg",
  authDomain: "personal-blog-8decb.firebaseapp.com",
  projectId: "personal-blog-8decb",
  storageBucket: "personal-blog-8decb.appspot.com",
  messagingSenderId: "473768411808",
  appId: "1:473768411808:web:c464d23c531b8bdaa4bfc5",
  measurementId: "G-6F04591W4N",
};

if (!getApps().length) {
  initializeApp(firebaseConfig);
}

const db = getFirestore();

//Reads all the posts in the database
export const getPosts = async () => {
  const q = query(collection(db, "posts"), orderBy("date", "desc"));
  const querySnapShot = await getDocs(q);
  const posts = querySnapShot.docs.map((doc) => ({
    ...doc.data(),
    id: doc.id,
    date: doc.data().date?.toDate().getTime(),
  }));
  return posts;
};

// Get one post from database based on the slug.
export const getPostBySlug = async (slug) => {
  const docRef = doc(db, "posts", `${slug}`);
  const docSnap = await getDoc(docRef);

  if (docSnap.exists()) {
    return docSnap.data();
  } else {
    console.log("No Such Document");
  }
};

// Adds posts to the database
export const createPost = async (post) => {
  await setDoc(doc(db, "posts", `${post.slug}`), {
    title: post.title,
    content: post.content,
    date: Timestamp.fromDate(new Date()),
  });
};

export const auth = getAuth();
export const googleAuthProvider = new GoogleAuthProvider();

And here is the slug page.

import { async } from "@firebase/util";
import { useRouter } from "next/router";
import { getPostBySlug } from "../../lib/firebase";
import moment from "moment";

export async function getServerSideProps() {
  const post = await getPostBySlug();

  return {
    props: {
      post,
    },
  };
}

export default function PostPage({ post }) {
  <div className="post">
    <h1>{post.title}</h1>
    <span>Published {moment(post.date).format("LL")}</span>
    <p dangerouslySetInnerHTML={{ __html: post.content }}></p>
  </div>;
}

Thanks in advance.

So here is how I got it to work. First I changed the firebase read file to a custom query.

// Get one post from database based on the slug.
export const getPostBySlug = async (slug) => {
  const q = query(collection(db, "posts"), where("slug", "==", `${slug}`));
  const querySnapShot = await getDocs(q);
  const post = querySnapShot.docs.map((doc) => ({
    ...doc.data(),
    id: doc.id,
    date: doc.data().date?.toDate().getTime(),
  }));
  return post;

I had to do it this way because of the timestamp I used with firestore. I couldn't figure out any other way to serialize it to json.

Next I changed the getServerSideProps function in the slug js file to take a context query.

export async function getServerSideProps(context) {
  const post = await getPostBySlug(context.query.slug);
  console.log("this is the severside props: ", post);

  return {
    props: {
      post,
    },
  };
}

After that it worked fine. There are probably better approached to this but this is what worked for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM