NextJS构建后CRUD功能失效,数据更新无响应求助
问题原因
Next.js 默认在 npm run build 时执行静态生成(SSG),页面数据在构建阶段就被固化。dev 模式下页面会在每次请求时重新获取数据,CRUD 功能正常;但生产环境(或 build 后启动)中,静态页面不会主动刷新,导致删除/更新数据后页面内容无变化。
解决方案
根据数据更新频率选择合适的渲染策略,以下是具体实现:
1. 使用 SSR(服务端渲染)
适合需要实时同步数据的场景,每次用户访问页面时,服务器都会重新查询数据库并返回最新数据。
修改页面组件
import { PrismaClient } from '@prisma/client' // 避免生产环境创建多个Prisma实例 const prisma = global.prisma || new PrismaClient() if (process.env.NODE_ENV !== 'production') global.prisma = prisma export default function PerfumeList({ perfumes }) { const handleDelete = async (perfumeId) => { // 调用后端API执行删除 await fetch(`/api/perfumes/${perfumeId}`, { method: 'DELETE' }) // 删除后刷新页面获取最新数据(简单实现,也可结合React状态管理局部更新) window.location.reload() } return ( <div className="perfume-list"> {perfumes.map(perfume => ( <div key={perfume.id} className="perfume-item"> <h3>{perfume.name}</h3> <button onClick={() => handleDelete(perfume.id)}>删除</button> </div> ))} </div> ) } // 服务端获取数据 export async function getServerSideProps() { try { const perfumes = await prisma.perfume.findMany() // 将Prisma对象序列化为普通JSON(避免Next.js序列化报错) return { props: { perfumes: JSON.parse(JSON.stringify(perfumes)) } } } catch (err) { console.error('获取数据失败:', err) return { props: { perfumes: [] } } } }
新增删除API路由
在 pages/api/perfumes/[id].js 创建API处理删除请求:
import { PrismaClient } from '@prisma/client' const prisma = global.prisma || new PrismaClient() if (process.env.NODE_ENV !== 'production') global.prisma = prisma export default async function handler(req, res) { const { id } = req.query if (req.method !== 'DELETE') { return res.status(405).json({ message: '仅支持DELETE方法' }) } try { await prisma.perfume.delete({ where: { id } }) res.status(200).json({ message: '删除成功' }) } catch (err) { res.status(500).json({ message: '删除失败', error: err.message }) } }
2. 使用 ISR(增量静态再生)
适合数据更新频率不高的场景,兼顾静态页面的性能和数据新鲜度。页面在构建时生成静态版本,之后每隔指定时间或按需重新生成。
仅需将上述 getServerSideProps 替换为 getStaticProps,并添加 revalidate 参数:
export async function getStaticProps() { const perfumes = await prisma.perfume.findMany() return { props: { perfumes: JSON.parse(JSON.stringify(perfumes)) }, revalidate: 60 // 每60秒重新生成页面(可根据需求调整) } }
3. 客户端局部更新(可选)
如果不想刷新页面,可在删除后通过客户端重新请求数据并更新组件状态:
import { useState, useEffect } from 'react' export default function PerfumeList() { const [perfumes, setPerfumes] = useState([]) // 初始加载数据 useEffect(() => { fetchPerfumes() }, []) const fetchPerfumes = async () => { const res = await fetch('/api/perfumes') const data = await res.json() setPerfumes(data) } const handleDelete = async (perfumeId) => { await fetch(`/api/perfumes/${perfumeId}`, { method: 'DELETE' }) // 删除后重新获取数据更新状态 fetchPerfumes() } return ( <div className="perfume-list"> {perfumes.map(perfume => ( <div key={perfume.id} className="perfume-item"> <h3>{perfume.name}</h3> <button onClick={() => handleDelete(perfume.id)}>删除</button> </div> ))} </div> ) }
同时需要新增获取所有香水的API路由 pages/api/perfumes.js:
import { PrismaClient } from '@prisma/client' const prisma = global.prisma || new PrismaClient() if (process.env.NODE_ENV !== 'production') global.prisma = prisma export default async function handler(req, res) { if (req.method === 'GET') { try { const perfumes = await prisma.perfume.findMany() res.status(200).json(perfumes) } catch (err) { res.status(500).json({ error: err.message }) } } else { res.status(405).json({ message: '仅支持GET方法' }) } }
常见问题排查
- 之前
getServerSideProps失败,大概率是Prisma实例重复创建或数据序列化问题:生产环境需确保Prisma实例单例,且将查询结果转为普通JSON(JSON.parse(JSON.stringify(perfumes)))。 - Vercel部署时需添加环境变量(如
DATABASE_URL),确保Prisma能连接到MongoDB。
内容的提问来源于stack exchange,提问作者kmurp62rulz
相关产品推荐
相关产品推荐

