You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React客户端按ID获取事件数据页面空白问题排查

问题描述

我想从SQL表中获取指定事件的数据,期望在客户端URL(http://localhost:3000/dashboard/)后添加对应的keyInfo_id时,页面只展示该ID的事件数据,而非全部事件。但目前访问http://localhost:3000/dashboard/3(3是MySQL生成的事件ID)时,页面空白无内容,不清楚原因。


服务端代码

/* GET event listing by ID */
router.get('/:keyInfo_id', async function (req, res, next) {
  let { keyInfo_id } = req.params;

  try {
    let result = await db(`SELECT activities.keyInfo_id, date, title, deadline, activities_id, activityName, description, price, location FROM activities INNER JOIN keyInfo ON keyInfo.keyInfo_id = activities.keyInfo_id WHERE keyInfo.keyInfo_id = ${keyInfo_id} `);

    let event = result.data;
    if (event.length !== 0) {
      res.send(event);
    } else {
      // event array is empty... no event found
      res.status(404).send({ error: 'Event not found' });
    }
  }catch (err) {
    res.status(500).send({error: err.message});
  }
});

客户端React代码

function App() {
  let [allEvents, setAllEvents] = useState([]);

  // useEffect() will call getEvent() when App is mounted on the DOM
  useEffect(() => {
    getEvent();  
  }, []);
  // the empty [] means only call it once

  //Get all the events
  async function getEvent() {
    try {
      let response = await fetch('/event');
      if (response.ok) {
        let data = await response.json();
        setAllEvents(data);
      } else {
        console.log(`Server error: ${response.status}: ${response.statusText}`);
      }
    } catch(err) {
      console.log(`Network error: ${err.message}`);
    }
  }

  // Get all the events by ID
  async function getEvent(id) {
    try {
      let response = await fetch('/:keyInfo_id');
      if (response.ok || response === id ) {
        let data = await response.json();
        setAllEvents(data);
      } else {
        console.log(`Server error: ${response.status}: ${response.statusText}`);
      }
    } catch(err) {
      console.log(`Network error: ${err.message}`);
    }
  }
}

问题分析与修复方案

核心问题点

  1. 路由未读取URL参数:React组件没有从/dashboard/:keyInfo_id路径中提取ID参数,也没有根据参数触发单个事件的请求。
  2. 接口请求地址错误:获取单个事件的getEvent(id)函数中,请求URL写死为/:keyInfo_id,这不是有效接口地址,需替换为带实际ID的路径。
  3. 函数重名冲突:两个getEvent函数同名,导致后定义的函数覆盖前一个,初始化调用的无参getEvent实际无效。
  4. SQL注入风险:直接将keyInfo_id拼接进SQL语句,存在安全漏洞。

修复步骤

1. 处理React路由,读取URL参数

使用react-router-dom获取URL中的ID参数,并根据参数决定请求全部事件还是单个事件:

import { useParams } from 'react-router-dom';

function App() {
  let [allEvents, setAllEvents] = useState([]);
  const { keyInfo_id } = useParams(); // 提取URL中的ID参数

  useEffect(() => {
    if (keyInfo_id) {
      getEventById(keyInfo_id); // 有ID则请求单个事件
    } else {
      getAllEvents(); // 无ID则请求全部事件
    }
  }, [keyInfo_id]); // ID变化时重新请求

  // 重命名函数避免冲突,获取全部事件
  async function getAllEvents() {
    try {
      let response = await fetch('/event');
      if (response.ok) {
        let data = await response.json();
        setAllEvents(data);
      } else {
        console.log(`Server error: ${response.status}: ${response.statusText}`);
      }
    } catch(err) {
      console.log(`Network error: ${err.message}`);
    }
  }

  // 修复请求地址,获取单个事件
  async function getEventById(id) {
    try {
      let response = await fetch(`/event/${id}`); // 替换为实际接口地址
      if (response.ok) {
        let data = await response.json();
        setAllEvents(data);
      } else if (response.status === 404) {
        console.log('事件不存在');
        setAllEvents([]);
      } else {
        console.log(`Server error: ${response.status}: ${response.statusText}`);
      }
    } catch(err) {
      console.log(`Network error: ${err.message}`);
    }
  }

  // 渲染事件数据
  return (
    <div>
      {allEvents.length === 0 ? (
        <p>暂无事件数据</p>
      ) : (
        allEvents.map(event => (
          <div key={event.keyInfo_id}>
            <h3>{event.title}</h3>
            <p>{event.description}</p>
            {/* 渲染其他事件字段 */}
          </div>
        ))
      )}
    </div>
  );
}

2. 修复服务端SQL注入问题

改用参数化查询,避免直接拼接SQL:

router.get('/:keyInfo_id', async function (req, res, next) {
  let { keyInfo_id } = req.params;

  try {
    // 参数化查询,语法根据使用的数据库库调整(示例为mysql2)
    let [result] = await db.query(
      `SELECT activities.keyInfo_id, date, title, deadline, activities_id, activityName, description, price, location 
       FROM activities 
       INNER JOIN keyInfo ON keyInfo.keyInfo_id = activities.keyInfo_id 
       WHERE keyInfo.keyInfo_id = ?`,
      [keyInfo_id]
    );

    let event = result;
    if (event.length !== 0) {
      res.send(event);
    } else {
      res.status(404).send({ error: 'Event not found' });
    }
  }catch (err) {
    res.status(500).send({error: err.message});
  }
});

3. 确认接口路由前缀

确保服务端路由挂载前缀为/event,比如:

// app.js中挂载路由
const eventRouter = require('./routes/event');
app.use('/event', eventRouter);

这样服务端/:keyInfo_id路由对应的完整接口地址为/event/3,与客户端请求地址匹配。


内容的提问来源于stack exchange,提问作者Kelly Tran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 10:52:54