React无法渲染Express后端PostgreSQL数据问题排查
问题:React前端无法渲染PostgreSQL返回的怪物数据
问题背景
- Express后端运行在3100端口,
http://localhost:3100/monsters可正常返回怪物数据,Postman请求返回200状态码,但前端请求返回304状态码 - 后端控制台能打印查询到的怪物数据,但React前端仅显示表格表头,
monsters数组为空
后端代码(server.js)
require("dotenv").config(); const cors = require("cors") const db = require("./db"); // Express Application setup const express = require("express"); const morgan = require("morgan"); const app = express(); const bodyParser = require("body-parser"); const port = process.env.PORT; app.listen(port, () => { console.log(`Server is UP and running and listening on port ${port}`); }) app.use(cors()); app.use(bodyParser.json()); // HTTP request logger middleware app.use(morgan("dev")); // Get All Monsters app.get('/monsters', async (req, res) => { const results = await db.query(`select * from monsters`, (err, results) => { if (!err) { console.log(results) res.send(results.rows); } }); db.end; })
前端相关代码
App.js
import './App.css'; import MainComponent from './components/MainComponent'; import Info from './components/Info'; import Rules from './components/Rules'; import Rulebooks from './components/Rulebooks'; import Monsters from './components/Monsters'; import Adventures from './components/Adventures'; import Contact from './components/Contact'; import { Routes, Route } from 'react-router-dom'; import MonsterInfo from './components/MonsterInfo'; import { MonsterContextProvider } from './context/MonsterContext'; function App() { return ( <MonsterContextProvider> <div> <Routes> <Route path="/" element={<MainComponent />} /> <Route path="/info" element={<Info />} /> <Route path="/rules" element={<Rules />} /> <Route path="/rulebooks" element={<Rulebooks />} /> <Route path="/monsters" element={<Monsters />} /> {/* <Route path="/monsters/:id" element={<MonsterInfo />} /> */} <Route path="/adventures" element={<Adventures />} /> <Route path="/contact" element={<Contact />} /> </Routes> </div> </MonsterContextProvider> ) }; export default App;
MonsterContext.js
import React, { useState, createContext } from "react"; export const MonsterContext = createContext(); export const MonsterContextProvider = props => { const [monsters, setMonsters] = useState([]) // const addMonsters = (monsters) => { // setMonsters([...monsters, monsters]); // } return ( <MonsterContext.Provider value={{ monsters: monsters, setMonsters }}> {props.children} </MonsterContext.Provider> ) }
MonsterFinder.js
import axios from "axios"; export default axios.create({ baseURL: "http://192.168.0.118:3100/" });
MonsterList.jsx
import "./Monsters.css"; import React, { useEffect, useContext } from 'react'; import MonsterFinder from "../apis/MonsterFinder"; import { useNavigate, Link } from "react-router-dom"; import { MonsterContext } from '../context/MonsterContext'; const MonsterList = (props) => { const { monsters, setMonsters } = useContext(MonsterContext); const navigate = useNavigate() useEffect(() => { const fetchData = async () => { try { const response = await MonsterFinder.get("/monsters"); setMonsters(response.data.data.monsters); } catch (err) {} }; fetchData(); }, []); return ( <div className="app-container"> <h1>Monsters</h1> <table> <thead> <tr> <th> </th> <th>Cr</th> <th>Name</th> <th>Source</th> <th>Type</th> <th>Size</th> <th>Alignment</th> <th>Tag</th> <th>Info</th> </tr> </thead> <tbody> {monsters.map((monster) => { return ( <tr> <td><img src={require(`../media/${monster.Image}`)} alt={monster.Name} height="25" width="25" /></td> <td>{monster.Cr}</td> <td>{monster.Name}</td> <td>{monster.Source}</td> <td>{monster.Type}</td> <td>{monster.Size}</td> <td>{monster.Alignment}</td> <td>{monster.Tag}</td> <td><button className="button"><Link className="links" to={`/monsterinfo/${monster.Name}`}>Info</Link></button></td> </tr> ); })} </tbody> </table> </div> ) }; export default MonsterList
问题排查与修复方案
经排查,前端存在两处关键错误:
- 数据获取路径错误:后端直接返回怪物数组,但前端代码中错误使用
response.data.data.monsters来获取数据,应改为response.data。
修复后代码:const response = await MonsterFinder.get("/monsters"); setMonsters(response.data); - 字段名大小写不匹配:前端渲染时使用大写字段名(如
monster.Image、monster.Name),但后端从PostgreSQL返回的是小写字段名(如monster.image、monster.name),导致无法正确读取数据。
修复需将前端渲染代码中的字段名改为小写,示例:<td><img src={require(`../media/${monster.image}`)} alt={monster.name} height="25" width="25" /></td> <td>{monster.cr}</td> <td>{monster.name}</td> <td>{monster.source}</td> <td>{monster.type}</td> <td>{monster.size}</td> <td>{monster.alignment}</td> <td>{monster.tag}</td>
注:使用模拟JSON数据时可正常渲染,说明问题完全集中在前端数据处理环节,304状态码为浏览器缓存机制导致,不影响数据正常获取,修复上述两处错误后即可正常渲染表格数据。
内容的提问来源于stack exchange,提问作者ray55nl
相关产品推荐
相关产品推荐

