React前端bookdata变量在服务端交互后变为null的问题求助
问题描述
与服务端完成交互后,bookdata变量变为null,页面无法显示任何信息。所有查询请求均能正常返回数据,推测问题出在前端。尝试过多种方法限制bookdata仅更新一次,但均未成功,耗时数小时仍未解决,恳请帮忙排查。
前端代码
import { useEffect, useState } from 'react' import { useLocation } from 'react-router-dom'; import axios from 'axios'; export default function Book() { interface Book { id_ksiazki: number; tytul: string; autor: string; cena: Float32Array; wydawnictwo: string; data_premiery: string; liczba_stron: number; } const [bookdata,setBookdata] = useState<Book>(); const location = useLocation(); const searchParams = new URLSearchParams(location.search); const id = searchParams.get('id'); const sendDataToBackend = async () => { axios.get('http://localhost:3000/book', { params: { id: id, } }) .then(response => { const data = response.data; // 从后端获取的数据 }) .catch(error => { console.error('GET请求错误:', error); }); }; useEffect(() => { if (id) { sendDataToBackend(); } axios.get('http://localhost:3000/book', { params: { id: id, } }) .then(response => { const data = response.data; // 获取到的数据 if(!bookdata) { setBookdata(data); console.log(data); } }) .catch(error => { console.error('GET请求错误:', error); }); }, [id]); return ( <div id="book-page"> <h1>书籍页面</h1> <h2>{bookdata?.tytul}</h2> <h3>{bookdata?.autor}</h3> <h4>{bookdata?.wydawnictwo}</h4> </div> ); }
后端代码
import express from 'express' import cors from 'cors' import mysql from 'mysql2' //import bodyParser from 'body-parser' //import bcrypt from 'bcrypt' //import jwt from 'jsonwebtoken' //import dotenv from 'dotenv' const corsOptions = { origin: 'http://localhost:5173', }; const app = express(); app.use(cors(corsOptions)); app.use(express.json()); const pool = mysql.createPool({ host: 'localhost', user: 'root', password: '', database: 'shelfparrot' }).promise() app.get('/sprzedane', async (req, res) => { try { const [row] = await pool.query("SELECT COUNT(*) AS sprzedane FROM zamowienia"); const wynik = row[0]; res.json(wynik); // 返回结果为JSON } catch (error) { console.error(error); res.status(500).json({ message: "服务器错误" }); } }); app.get('/ksiazki', async (req,res) => { try { const [row] = await pool.query("SELECT * FROM ksiazki"); res.json(row) } catch (error) { console.log(error); res.status(500).json({ message: "服务器错误" }); } }) app.get('/book', async (req, res) => { try { const id = req.query.id; const zap = "SELECT * FROM ksiazki WHERE id_ksiazki = ?"; const [row] = await pool.query(zap, id + 1); console.log(row); res.json(row); } catch (error) { console.log(error); res.status(500).json({ message: "服务器错误" }); } }); app.listen(3000, () => { console.log('服务器运行在3000端口'); });
控制台输出(打印了两次)
[{…}] 0: autor: "Karol Dickens" cena: 50 data-premiery: "2022-05-31" id_ksiazki: 1 liczba-stron: 600 tytul: "Opowieść o dwóch miastach" wydawnictwo: "Wydawnictwo Zysk i S-ka" [[Prototype]]: Object length: 1 [[Prototype]]: Array(0)
问题排查与修复方案
核心问题点
- 数据格式不匹配:后端返回的是包含单个对象的数组,但前端
Book接口定义的是单个对象类型,直接将数组赋值给bookdata会导致后续无法正确读取属性。 - 重复请求+错误的状态判断:
useEffect中同时发起两次相同请求,且if(!bookdata)的判断依赖闭包捕获的初始值(始终为undefined),会导致重复赋值;若某次请求返回空数组,bookdata会被设为数组,自然无法读取对象属性。 - 字段名与类型不匹配:
- 后端返回字段为
data-premiery、liczba-stron,但前端接口定义为data_premiery、liczba_stron,下划线与短横线不匹配导致字段映射失败; - 前端将
cena定义为Float32Array,但后端返回的是普通数字,类型不兼容。
- 后端返回字段为
- 后端参数错误:
id + 1会将字符串类型的id拼接为id1(如id为"1"时变成"11"),导致查询错误。
修复步骤
1. 修正后端数据返回与参数问题
// 后端/book接口修改 app.get('/book', async (req, res) => { try { const id = req.query.id; const zap = "SELECT * FROM ksiazki WHERE id_ksiazki = ?"; // 参数传入数组避免字符串拼接问题,移除错误的id+1 const [row] = await pool.query(zap, [id]); console.log(row); // 返回单个对象而非数组,若查询不到则返回null res.json(row[0] || null); } catch (error) { console.log(error); res.status(500).json({ message: "服务器错误" }); } });
2. 修正前端接口定义
interface Book { id_ksiazki: number; tytul: string; autor: string; cena: number; // 改为与后端匹配的number类型 wydawnictwo: string; "data-premiery": string; // 与后端字段名保持一致,或让后端用AS重命名为下划线格式 "liczba-stron": number; }
3. 清理useEffect中的重复请求,优化状态更新
useEffect(() => { if (!id) return; // 移除重复请求,只保留一个 axios.get('http://localhost:3000/book', { params: { id } }) .then(response => { const book = response.data; setBookdata(book); }) .catch(error => { console.error('请求失败:', error); }); }, [id]);
4. 可选:添加加载状态优化体验
const [loading, setLoading] = useState(true); useEffect(() => { if (!id) return; setLoading(true); axios.get('http://localhost:3000/book', { params: { id } }) .then(response => { const book = response.data; setBookdata(book); }) .catch(error => { console.error('请求失败:', error); }) .finally(() => { setLoading(false); }); }, [id]); // 渲染逻辑调整 return ( <div id="book-page"> <h1>书籍页面</h1> {loading ? ( <p>加载中...</p> ) : bookdata ? ( <> <h2>{bookdata.tytul}</h2> <h3>{bookdata.autor}</h3> <h4>{bookdata.wydawnictwo}</h4> </> ) : ( <p>未找到该书籍</p> )} </div> );
内容的提问来源于stack exchange,提问作者Michaju
相关产品推荐
相关产品推荐

