React组件用Prisma展示数据报错:PrismaClient无法在浏览器运行
解决React组件中使用Prisma Client报错"Uncaught Error: PrismaClient is unable to be run in the browser."
问题背景
在React应用的Table组件中直接导入Prisma Client查询数据库,触发错误:Uncaught Error: PrismaClient is unable to be run in the browser.,无法正常展示数据。
错误原因
Prisma Client是仅服务端可用的ORM工具,它需要直接访问数据库文件/连接字符串,而前端代码运行在用户浏览器中,既无法直接连接服务端数据库,也会暴露敏感的数据库配置信息,因此Prisma禁止在浏览器环境中初始化Client。
解决方案
必须通过服务端API接口中转数据:前端发送HTTP请求到服务端,服务端用Prisma操作数据库后返回结果给前端。以下是具体实现步骤:
1. 创建服务端API路由
以Next.js的API路由为例(如果用Express等框架,逻辑类似),在pages/api/historico.js文件中编写接口:
import { prisma } from '../../prisma/prismaScript'; export default async function handler(req, res) { // 获取历史数据 if (req.method === 'GET') { try { const historico = await prisma.historico.findMany({ include: { Barcaca: true, Inspetor: true } // 按需关联查询关联表数据 }); res.status(200).json(historico); } catch (error) { res.status(500).json({ error: '获取数据失败' }); } } // 新增数据 else if (req.method === 'POST') { try { const newItem = await prisma.historico.create({ data: req.body }); res.status(201).json(newItem); } catch (error) { res.status(500).json({ error: '新增数据失败' }); } } }
2. 修改前端Table组件
移除Prisma导入,改用fetch请求服务端API获取和提交数据,同时修复状态初始化的问题:
import React, { useState, useEffect, Fragment } from "react"; import ReadOnlyRow from "./ReadOnlyRow"; import "./table.css" const Table = () => { const [contacts, setContacts] = useState([]); const [addFormData, setAddFormData] = useState({ data: "", barcaca: "", inspecao: "", inspetor: "", anotacoes: "", relatorio: "" }); // 组件挂载时获取数据 useEffect(() => { const fetchHistorico = async () => { try { const response = await fetch('/api/historico'); const data = await response.json(); setContacts(data); } catch (error) { console.error('获取数据失败:', error); } }; fetchHistorico(); }, []); const handleAddFormChange = (event) => { const fieldName = event.target.getAttribute("name"); const fieldValue = event.target.value; setAddFormData(prev => ({ ...prev, [fieldName]: fieldValue })); }; const handleAddFormSubmit = async (event) => { event.preventDefault(); try { const response = await fetch('/api/historico', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ Data: addFormData.data, BarcacaId: addFormData.barcaca, Inspecao: addFormData.inspecao, InspetorId: addFormData.inspetor, Anotacoes: parseInt(addFormData.anotacoes), Relatorio: addFormData.relatorio }) }); if (response.ok) { const newItem = await response.json(); setContacts(prev => [...prev, newItem]); // 重置表单 setAddFormData({ data: "", barcaca: "", inspecao: "", inspetor: "", anotacoes: "", relatorio: "" }); } } catch (error) { console.error('新增数据失败:', error); } }; return ( <div className="app-container"> <form> <table className="table table-hover"> <thead> <tr className="table-primary"> <th>Data</th> <th>Barcaça</th> <th>Inspeção</th> <th>Inspetor</th> <th>Anotações</th> <th>Relatório</th> </tr> </thead> <tbody> {contacts.map((contact) => ( <Fragment key={contact.ID}> <ReadOnlyRow contact={contact} /> </Fragment> ))} </tbody> </table> </form> <h2>Add a Contact</h2> <form onSubmit={handleAddFormSubmit}> <input type="date" name="data" required placeholder="DD/MM/AAAA" value={addFormData.data} onChange={handleAddFormChange} /> <input type="text" name="barcaca" required placeholder="Barcaça ID" value={addFormData.barcaca} onChange={handleAddFormChange} /> <input type="text" name="inspecao" required placeholder="Inspeção" value={addFormData.inspecao} onChange={handleAddFormChange} /> <input type="text" name="inspetor" required placeholder="Inspetor ID" value={addFormData.inspetor} onChange={handleAddFormChange} /> <input type="number" name="anotacoes" required placeholder="Anotações" value={addFormData.anotacoes} onChange={handleAddFormChange} /> <input type="text" name="relatorio" required placeholder="Relatório" value={addFormData.relatorio} onChange={handleAddFormChange} /> <button type="submit">Adicionar</button> </form> </div> ); }; export default Table;
关键注意事项
- 前端永远不能直接操作数据库,所有数据库操作必须通过服务端API完成
- Prisma Schema中的字段名是大写开头(如
Data、BarcacaId),前端提交数据时要严格对应字段名 - 如果需要处理文件上传,需修改API支持
multipart/form-data格式,当前示例简化为文本输入 - 生产环境需为API添加身份验证,防止非法访问数据库
内容的提问来源于stack exchange,提问作者Hugo Machado Fabris
相关产品推荐
相关产品推荐

