Next.js中用getStaticPaths/Props结合React Context遇ISR错误求助
Next.js ISR 产品详情页实现错误修复
我用Next.js、TypeScript和Firebase开发简易落地页,把Firestore的产品数据存在React Context里,尝试用ISR实现localhost:3000/product/[slug].tsx产品详情页时出现错误,相关代码如下:
interface Props { slug:Products } const ProductPage: NextPage<Props> = ({ slug }) => { const { products } = useContext(DbContext) const product = products.filter(product => product.slug === `${slug}`) return ( <MainLayout title={``} pageDescription={''} imageFullUrl={''}> // product tsx </MainLayout> ) } export const getStaticPaths: GetStaticPaths = async (ctx) => { const { products } = useContext(DbContext) const slugs = products.map(product => product.slug) return { paths: slugs.map((slug) => ({ params: { slug } })), fallback: "blocking" } } export const getStaticProps: GetStaticProps = async ({ params }) => { const { slug } = params as { slug: string } if (!slug) { return { redirect: { destination: "/", permanent: false } } } return { props: { slug }, revalidate:86400 } } export default ProductPage
错误截图:
问题根源
getStaticPaths中调用useContext:React Hooks仅能在React组件或自定义Hooks中使用,getStaticPaths是Next.js的静态生成函数,运行在非组件环境,无法访问React Context,这是直接触发报错的原因。- Props类型不匹配:
Props将slug定义为Products类型,但实际传递的是字符串,导致类型冲突。 - 依赖Context过滤产品:ISR场景下,应在服务端直接获取对应slug的产品数据,而非依赖客户端Context,否则易出现数据不一致或加载延迟问题。
修正后的代码
1. 修正getStaticPaths:直接从Firestore获取slug
import { db } from '../path/to/your/firebase/config'; // 导入你的Firebase配置文件 import { collection, getDocs } from 'firebase/firestore'; // ...其他组件代码 export const getStaticPaths: GetStaticPaths = async () => { // 直接连接Firestore获取所有产品的slug const productsCol = collection(db, 'products'); const productsSnapshot = await getDocs(productsCol); const slugs = productsSnapshot.docs.map(doc => doc.data().slug); return { paths: slugs.map(slug => ({ params: { slug } })), fallback: "blocking" } }
2. 修正getStaticProps:直接获取对应产品数据
import { query, where, getDocs } from 'firebase/firestore'; export const getStaticProps: GetStaticProps = async ({ params }) => { const { slug } = params as { slug: string }; if (!slug) { return { redirect: { destination: "/", permanent: false } }; } // 查询对应slug的产品 const productsCol = collection(db, 'products'); const productQuery = query(productsCol, where('slug', '==', slug)); const productSnapshot = await getDocs(productQuery); // 未找到产品则返回404 if (productSnapshot.empty) { return { notFound: true }; } const product = productSnapshot.docs[0].data() as Products; return { props: { product }, revalidate: 86400 // 24小时自动重新验证数据 } }
3. 修正组件与Props定义
interface Props { product: Products; // 直接接收完整产品数据 } const ProductPage: NextPage<Props> = ({ product }) => { // 直接使用传入的product,无需从Context过滤 return ( <MainLayout title={product.name} pageDescription={product.description} imageFullUrl={product.imageUrl} > {/* 渲染产品内容 */} <h1>{product.name}</h1> <p>{product.description}</p> {/* 其他产品信息渲染 */} </MainLayout> ) }
关键注意事项
- 静态生成/ISR相关函数(
getStaticPaths/getStaticProps)不能调用React Hooks,必须直接从数据源获取数据。 - ISR模式下,优先在服务端获取当前页面的精准数据,减少客户端依赖,既提升加载速度又保证数据一致性。
- TypeScript类型定义需与实际数据匹配,避免类型不匹配引发的错误。
内容的提问来源于stack exchange,提问作者guido
相关产品推荐
相关产品推荐

