MERN栈React Hooks问题:添加筛选后Bus数据无法显示
MERN栈班车列表不显示问题排查与解决
问题概述
在MERN栈项目中添加筛选功能后,页面无法显示Bus数据(数据库中存在该数据且可正常创建新数据),回滚代码后问题依然存在。控制台抛出React Hooks依赖警告:Line 41:6: React Hook useEffect has a missing dependency: 'getBuses'. Either include it or remove the dependency array react-hooks/exhaustive-deps,同时Bus数据未成功从后端传输到前端。
核心问题分析
- React闭包与依赖缺失:
getBuses函数依赖filters状态,但useEffect使用空依赖数组仅执行一次,导致函数捕获的是初始空filters,后续状态更新无法触发重新请求;ESLint的依赖警告是表象,背后的闭包问题会导致请求逻辑异常。 - 后端接口两个关键问题:
get-all-buses接口添加了authMiddleware但未验证前端是否携带有效Token,可能导致请求被拦截,数据无法返回;同时接口未使用前端传递的filters参数,等于未实现筛选逻辑。- 接口响应存在多处拼写错误(
seccess、meggage),会导致前端判断response.data.success时出错,无法正确设置buses状态。
- 前端渲染大小写不匹配:MongoDB Schema中
status字段默认值为'Yet to Start'(首字母大写),但前端过滤条件使用bus.status === "Yet to start"(start小写),导致过滤后无数据显示。
代码修复方案
前端Home组件修复
import React, { useEffect, useState, useCallback } from 'react' import { useDispatch, useSelector } from 'react-redux' import { axiosInstance } from '../helpers/axiosInstance'; import { HideLoading, ShowLoading } from '../redux/alertsSlice'; import { Col, Row, message } from 'antd'; import Bus from '../components/Bus'; function Home() { const { user } = useSelector(state => state.users) const [filters, setFilters] = useState({}); const dispatch = useDispatch(); const [buses, setBuses] = useState([]); // 用useCallback缓存函数,避免重复创建导致无限循环 const getBuses = useCallback(async () => { const tempFilters = {}; Object.keys(filters).forEach((key) => { if (filters[key]) { tempFilters[key] = filters[key]; } }) try { dispatch(ShowLoading()) const response = await axiosInstance.post( "/api/buses/get-all-buses", tempFilters ); dispatch(HideLoading()); if (response.data.success) { setBuses(response.data.data); } else { message.error(response.data.message || '获取班车数据失败'); } } catch (error) { dispatch(HideLoading()); message.error(error.message || '网络请求失败'); } }, [filters, dispatch]); // 声明函数依赖 useEffect(() => { getBuses(); }, [getBuses]); // 将getBuses加入依赖数组 // 修复status过滤的大小写匹配问题 const filteredBuses = buses.filter((bus) => bus.status === "Yet to Start"); return ( <div> <div className='my-3 card p-2'> <Row gutter={10}> <Col lg={6} sm={24}> <input type='text' placeholder='出发地' value={filters.from || ''} onChange={(e) => setFilters(prev => ({ ...prev, from: e.target.value }))} /> </Col> <Col lg={6} sm={24}> <input type='text' placeholder='目的地' value={filters.to || ''} onChange={(e) => setFilters(prev => ({ ...prev, to: e.target.value }))} /> </Col> <Col lg={6} sm={24}> <input type='date' placeholder='行程日期' value={filters.journeyDate || ''} onChange={(e) => setFilters(prev => ({ ...prev, journeyDate: e.target.value }))} /> </Col> <Col lg={6} sm={24}> <button className='primary-btn' onClick={getBuses}> 筛选 </button> </Col> </Row> </div> <div> <Row gutter={[15, 15]}> {filteredBuses.map((bus) => ( <Col lg={12} xs={24} sm={24} key={bus._id}> <Bus bus={bus} /> </Col> ))} </Row> </div> </div> ) } export default Home
后端busesRoute修复
const router = require('express').Router(); const Bus = require("../models/busModel") const authMiddleware = require("../middlewares/authMiddleware") // 添加班车 router.post('/add-bus', async (req, res) => { try { const existingBus = await Bus.findOne({ number: req.body.number }) if (existingBus) { return res.status(200).send({ success: false, // 修复拼写错误 message: '班车已存在', // 修复拼写错误 }) } const newBus = new Bus(req.body); await newBus.save(); return res.status(200).send({ success: true, message: '班车添加成功' }) } catch (error) { res.status(500).send({ success: false, message: error.message // 修复拼写错误 }) } }); // 更新班车 router.post("/update-bus", authMiddleware, async (req, res) => { try { await Bus.findByIdAndUpdate(req.body._id, req.body) return res.status(200).send({ success: true, message: '班车更新成功', }) } catch (error) { res.status(500).send({success: false, message: error.message}) // 修复拼写错误 } }); // 删除班车 router.post("/delete-bus", authMiddleware, async (req, res) => { try { await Bus.findByIdAndDelete(req.body._id) return res.status(200).send({ success: true, message: '班车删除成功', }) } catch (error) { res.status(500).send({success: false, message: error.message}) // 修复拼写错误 } }); // 获取所有班车:若为公开页面则移除authMiddleware,需登录则保留 router.post("/get-all-buses", /* authMiddleware, */ async (req, res) => { try { const filters = req.body; // 构建有效查询条件 const query = {}; if (filters.from) query.from = filters.from; if (filters.to) query.to = filters.to; if (filters.journeyDate) query.journeyDate = filters.journeyDate; const buses = await Bus.find(query); // 使用筛选条件查询 return res.status(200).send({ success: true, message: "班车数据获取成功", data: buses, }) } catch (error) { res.status(500).send({ success: false, message: error.message }) }; }) // 根据ID获取班车 router.post("/get-bus-by-id", authMiddleware, async (req, res) => { try { const bus = await Bus.findById(req.body._id); return res.status(200).send({ success: true, message: "班车数据获取成功", data: bus, }) } catch (error) { res.status(500).send({ success: false, message: error.message }) }; }) module.exports = router;
验证步骤
- 重启前后端服务,清除浏览器缓存
- 打开浏览器开发者工具,查看Network面板中
/api/buses/get-all-buses请求的响应状态与数据 - 确认页面正常显示班车列表,测试筛选功能是否生效
- 检查控制台是否还有React Hooks依赖警告
内容的提问来源于stack exchange,提问作者Вишневский Владислав
相关产品推荐
相关产品推荐

