简体   繁体   中英

NextJs getServerSideProps cannot fetch data from Cloud Firestore Web version 9

I am using NextJs version 12.0.10 and firebase version 9.6.6 which use a modular system to import it.

When I run the function from my service to fetch data from firebase/firestore , it returns an error saying Cannot access 'getStories' before initialization . I'm confident all the logic & syntax are correct, as it works perfectly when I fetch it from inside the page render function.

Here is my getServerSideProps function:
pages/index.js

import '@uiw/react-markdown-preview/markdown.css';
import { useContext } from 'react';
import { getStories } from '../lib/services/StoryService';
import { truncate } from 'lodash';
import { convertSecondsToHumanReadableDiff } from '../lib/utils/common';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { AuthContext } from '../pages/_app';
import Navigation from '../components/Navigation';

export async function getServerSideProps() {
  const fetchedStories = await getStories();

  const stories = fetchedStories.docs.map((story) => {
    return {
      ...story.data(),
      id: story.id,
      content: truncate(story.data().content, { length: 150, separator: '...' }),
    };
  });

  return { props: { stories } };
}

const Blog = ({ stories }) => {
  const router = useRouter();
  const { user } = useContext(AuthContext);

  return (
    <div>
      ...
    </div>
  );
};

export default Blog;

lib/firebase/firebase.js

import { initializeApp } from 'firebase/app';
import { getAnalytics } from 'firebase/analytics';
import { getFirestore } from 'firebase/firestore';
import { getAuth } from 'firebase/auth';

const firebaseConfig = {
  apiKey: 'XXX',
  authDomain: 'XXX',
  projectId: 'XXX',
  storageBucket: 'X',
  messagingSenderId: 'XXX',
  appId: 'XXX',
  measurementId: 'XXX',
};

const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);

export const database = getFirestore(app);
export const auth = getAuth(app);

lib/services/storyService.js

import {
  collection,
  query,
  getDocs,
  getDoc,
  setDoc,
  doc,
  serverTimestamp,
  orderBy,
} from 'firebase/firestore';
import { database } from '../firebase/firebase';
import slugify from 'slugify';
import { random } from 'lodash';

const storiesRef = collection(database, 'stories');

export const createStory = async (payload) => {
  const slugTitle = slugify(payload.title);
  const slug = slugTitle + '-' + random(0, 100000);
  const updatedPayload = {
    ...payload,
    slug,
    type: 'published',
    createdAt: serverTimestamp(),
  };

  return setDoc(doc(storiesRef, slug), updatedPayload);
};

export const getStories = async () => {
  const q = query(storiesRef, orderBy('createdAt', 'desc'));

  return getDocs(q);
};

export const getStoryBySlug = async (slug) => {
  const docRef = doc(database, 'stories', slug);

  return getDoc(docRef);
};

在此处输入图像描述

You are using getDocs , a client-side function of firebase, inside your getStories function, which is invoked in getServerSideProps, a node.js environment.

Instead you need to use the admin SDK for functions invoked in node.js environment (like getServerSideProps), eg like so:

    import * as admin from "firebase-admin/firestore";
    
    export const getStories = async () => {
     return await admin
      .getFirestore()
      .collection(database, 'stories')
      .orderBy('createdAt', 'desc')
      .get()
    };

    export const getStoryBySlug = async (slug) => {
     return await admin
      .getFirestore()
      .doc(database, 'stories', slug)
      .get()
    };

(sorry for the late answer, I still hope it helps OP or anyone else)

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