Next.js应用无法从Google Realtime Database拉取数据求助
解决Next.js从Firebase Realtime Database拉取数据的问题
先修复序列化错误
你遇到的SerializableError是因为getStaticProps里的res.json()没有加await,导致返回的data是一个Promise对象,而Next.js要求getStaticProps返回的props必须是可序列化的JSON类型。
修改getStaticProps:
export async function getStaticProps() { // 需添加具体节点路径,比如数据存在products节点下就加/products.json const res = await fetch('https://audiophile-a8abd-default-rtdb.firebaseio.com/products.json'); // 必须加await,res.json()是异步操作 const data = await res.json(); // 若返回的是key-value结构,转成数组方便遍历 const productList = Object.values(data); return { props: { data: productList, } } }
正确使用Firebase SDK获取数据(推荐)
你已经初始化了Firebase,但未使用Realtime Database的SDK,建议用官方SDK操作,避免fetch路径问题:
- 安装依赖:
npm install @firebase/database
- 在Firebase配置文件中初始化并导出数据库实例:
// firebase/firebase.js import { initializeApp } from "firebase/app"; import { getDatabase } from "firebase/database"; // 新增导入 const firebaseConfig = { // 你的配置信息 }; export const app = initializeApp(firebaseConfig); export const db = getDatabase(app); // 导出数据库实例
- 按需求选择数据获取方式:
静态生成(适合不频繁更新的数据)
修改getStaticProps:
import { ref, get } from "firebase/database"; import { db } from '../../firebase/firebase'; export async function getStaticProps() { const dbRef = ref(db, 'products'); // 指定要获取的节点 const snapshot = await get(dbRef); const data = snapshot.val(); const productList = Object.values(data); // 转成数组方便遍历 return { props: { data: productList, }, // 可选:设置重新验证时间,比如每60秒重新生成页面 revalidate: 60 } }
实时获取数据(数据变化时页面自动更新)
在客户端组件中监听数据变化:
import { useEffect, useState } from 'react'; import { ref, onValue } from "firebase/database"; import { db } from '../../firebase/firebase'; import CategoryHeader from '../../components/CategoryHeader'; import Product from './product'; export default function Categories() { const [productData, setProductData] = useState([]); useEffect(() => { const dbRef = ref(db, 'products'); // 监听数据变化,每次更新触发回调 const unsubscribe = onValue(dbRef, (snapshot) => { const data = snapshot.val(); const productList = Object.values(data); setProductData(productList); }); // 组件卸载时取消监听 return () => unsubscribe(); }, []); return ( <section> <CategoryHeader header="All Products"/> <div className="category"> <ul> {productData.map((item) => ( <li key={item.id}> <Product productName={item.name} productDescription={item.description} productImage={item.image.desktop} /> </li> ))} </ul> </div> </section> ) }
其他注意事项
- 页面中停止使用本地的
database.json,改用从getStaticProps传入的data或客户端监听获取的productData。 - 确保Firebase Realtime Database的规则允许读取(开发阶段可暂时设置为
"read": true, "write": true,上线后需配置安全规则)。
内容的提问来源于stack exchange,提问作者Micah Johnson
相关产品推荐
相关产品推荐

