React组件使用Knex获取数据库数据报错问题咨询
核心问题
你的实现思路从架构上就错了:React组件运行在终端用户的浏览器环境中,根本不能、也不允许直接连接数据库。
不管你把Knex相关的数据库操作文件移不移动到src目录,只要你试图在前端代码里直接import数据库操作逻辑,都不可能正常运行:浏览器没有Node.js运行环境,不支持net、fs等Node原生模块,Knex依赖的数据库驱动根本无法在浏览器里执行,你之前移动文件后触发的其他错误基本都是这个原因导致的。
你之前尝试用fetch调用http://localhost:3001接口的思路才是前后端分离场景下的正确方案,完全不需要在Express里写原生SQL——你之前写好的Knex操作逻辑完全可以直接在Express后端复用。
正确实现步骤
1. 拆分前后端代码职责
把项目代码按运行环境分成两个独立部分,不要混放:
- 前端部分(React代码,存放在React项目的
src/目录下):只负责页面渲染、交互逻辑,所有数据读写都通过HTTP请求调用后端接口获取 - 后端部分(Express + Knex代码,存放在独立的后端服务目录,比如和React项目平级的
server/文件夹):负责连接数据库、封装数据操作逻辑、对外提供HTTP接口
2. 调整后端Express代码
你之前写的db.js、library.js可以直接在后端复用,只需要新增对应接口路由即可,不需要写原生SQL:
后端服务入口文件(比如server/app.js)示例:
const express = require('express') const cors = require('cors') const library = require('./library') // 后端是Node环境,没有src目录导入限制,直接引用即可 const app = express() const port = 3001 // 配置跨域,否则前端请求会被浏览器同源策略拦截 app.use(cors()) // 新增查询菜谱的接口 app.get('/api/recipes', async (req, res) => { try { const recipes = await library.getAllRecipes() res.json({ code: 0, data: recipes }) } catch (err) { res.status(500).json({ code: 500, message: '查询菜谱失败' }) } }) app.listen(port, () => { console.log(`后端服务运行在 http://localhost:${port}`) })
修正你之前library.js里的逻辑问题:
function getAllRecipes() { return db .readRecipes() .then((result) => { return result }) .catch((err) => { logError(err) throw err // 把错误向上抛出,让上层路由能捕获到异常 }) // 删掉原代码finally块里的db.close(),不要每次操作完就关数据库连接 }
db.js的原有逻辑不需要改动,可以直接使用。
3. 调整前端React组件逻辑
删除组件里直接引用数据库文件的代码,改成通过HTTP请求调用后端接口:
const retrieveAllRecipes = async function () { try { const resp = await fetch('http://localhost:3001/api/recipes') const result = await resp.json() if (result.code === 0) { console.log(result.data) // 此处把返回的菜谱数据存入组件state,用于页面渲染即可 } } catch (err) { console.error('请求失败', err) } } // 可以在组件挂载时(比如useEffect钩子、componentDidMount生命周期)调用上述方法即可
常见踩坑提醒
- 不要在前端代码中引入任何仅能在Node.js环境运行的模块(包括数据库驱动、fs、path等系统模块),浏览器环境无法执行这类代码
- Knex是服务端数据库操作工具,仅能在Node.js后端环境运行,不要把相关代码打包到前端产物中
- 不要在单次数据库操作完成后调用
db.close(),Knex默认使用连接池复用连接,每次操作后关闭连接会导致后续请求数据库连接异常,只需要在服务彻底关闭时再断开连接即可 - 前后端分离联调时必须配置跨域,否则请求会被浏览器拦截
内容的提问来源于stack exchange,提问作者deadant88
相关产品推荐
相关产品推荐

