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

如何在ReactJS中实现日期范围筛选及动态数据渲染

功能实现方案

前端代码(React)

import { useState, useEffect } from 'react';
import { Line } from 'react-chartjs-2';

const BASE_URL = "http://localhost:8080/sites";
const SelectSingle = () => {
  const [sites, setSites] = useState([]);
  const [selectedCellName, setSelectedCellName] = useState('');
  const [startDate, setStartDate] = useState('');
  const [endDate, setEndDate] = useState('');
  const [filteredData, setFilteredData] = useState([]);

  // 日期格式转换:输入yyyy-mm-dd转成数据库存储的dd/mm/yyyy格式
  const formatDateToDb = (dateStr) => {
    const [year, month, day] = dateStr.split("-");
    return `${day}/${month}/${year}`;
  };

  // 将dd/mm/yyyy格式的字符串转成Date对象用于范围比较
  const parseDbDate = (dbDateStr) => {
    const [day, month, year] = dbDateStr.split("/");
    return new Date(year, Number(month)-1, day);
  };

  // 统一筛选逻辑
  const filterData = () => {
    if (!selectedCellName || !startDate || !endDate) return;
    const startObj = parseDbDate(formatDateToDb(startDate));
    const endObj = parseDbDate(formatDateToDb(endDate));

    const result = sites.filter(site => {
      // 匹配选中的站点
      if (site.Cell_Name !== selectedCellName) return false;
      // 匹配日期范围
      const currentDate = parseDbDate(site.Traffice_Date);
      return currentDate >= startObj && currentDate <= endObj;
    });
    setFilteredData(result);
  };

  // 组件挂载时拉取全量站点数据(数据量小可用此方案,数据量大建议走后端筛选)
  useEffect(() => {
    fetch(BASE_URL)
      .then(res => res.json())
      .then(data => setSites(data));
  }, []);

  // 筛选条件变更时重新过滤数据
  useEffect(() => {
    filterData();
  }, [selectedCellName, startDate, endDate]);

  // 图表数据组装
  const chartData = {
    labels: filteredData.map(item => item.Traffice_Date),
    datasets: [
      {
        label: "E_RAB_Setup_Success_Rate",
        backgroundColor: "rgba(75,192,192,1)",
        borderColor: "rgba(0,0,0,1)",
        borderWidth: 2,
        data: filteredData.map(item => item.E_RAB_Setup_Success_Rate),
      },
    ],
  };

  return (
    <div>
      <div className="data-class">
        <select onChange={(e) => setSelectedCellName(e.target.value)} value={selectedCellName}>
          <option value="">请选择站点</option>
          {/* 站点去重,避免下拉选项重复 */}
          {[...new Map(sites.map(site => [site.Cell_Name, site])).values()].map((site, index) => (
            <option value={site.Cell_Name} key={index}>
              {site.Cell_Name}
            </option>
          ))}
        </select>
        <h2>From</h2>
        <input
          type="date"
          value={startDate}
          onChange={(e) => setStartDate(e.target.value)}
          name="startDate"
        />
        <h2>To</h2>
        <input
          type="date"
          value={endDate}
          onChange={(e) => setEndDate(e.target.value)}
          name="endDate"
        />
      </div>
      <div>
        <table>
          <thead>
            <tr>
              <th>E_NodeB</th>
              <th>Cell_Name</th>
              <th>Date</th>
              <th>E_RAB_Setup_Success_Rate</th>
              <th>Data_Traffic_DL</th>
              <th>Data_Traffic_UL</th>
              <th>UL_Throughput</th>
            </tr>
          </thead>
          <tbody>
            {filteredData.map((site, index) => (
              <tr key={index}>
                <td>{site.eNodeB_Name}</td>
                <td>{site.Cell_Name}</td>
                <td>{site.Traffice_Date}</td>
                <td>{site.E_RAB_Setup_Success_Rate}</td>
                <td>{site.Data_Traffic_DL}</td>
                <td>{site.Data_Traffic_UL}</td>
                <td>{site.G_UL_Throughput_IK}</td>
              </tr>
            ))}
          </tbody>
        </table>

        <Line
          data={chartData}
          options={{
            title: {
              display: true,
              text: "Plot of E_RAB_Setup_Success_Rate",
              fontSize: 20,
            },
            legend: {
              display: true,
              position: "right",
            },
          }}
        />
      </div>
    </div>
  );
};

export default SelectSingle;

后端代码(Express+MySQL)

修复原有语法错误,新增支持参数化筛选的逻辑(数据量较大时推荐使用):

const express = require("express");
const cors = require("cors");
const mysql = require("mysql2");
const app = express();

const connection = mysql.createConnection({
  host: "localhost",
  user: "a",
  password: "123",
  database: "aa",
});

connection.connect((err) => {
  if (err) throw err;
  console.log("Connected to MySQL Server!");
});

app.use(cors());

app.get("/", function (req, res) {
  connection.query("SELECT * FROM africell_data LIMIT 10", (err, rows) => {
    if (err) throw err;
    res.json(rows);
  });
});

app.get("/sites", function (req, res) {
  const { cellName, startDate, endDate } = req.query;
  let sql = `SELECT eNodeB_Name,Cell_Name,Traffice_Date,E_RAB_Setup_Success_Rate,Data_Traffic_DL,Data_Traffic_UL,G_UL_Throughput_IK FROM africell_data`;
  let params = [];
  // 传入筛选参数则走范围查询逻辑
  if (cellName && startDate && endDate) {
    sql += ` WHERE Cell_Name = ? AND STR_TO_DATE(Traffice_Date, '%d/%m/%Y') BETWEEN STR_TO_DATE(?, '%d/%m/%Y') AND STR_TO_DATE(?, '%d/%m/%Y')`;
    params = [cellName, startDate, endDate];
  }
  connection.query(sql, params, (err, rows) => {
    if (err) throw err;
    res.json(rows);
  });
});

app.listen(8080, () => {
  console.log(`App running on port 8080`);
});

修复说明

  • 移除硬编码的站点名称,复用下拉框选中的站点值
  • 新增日期范围比较逻辑,支持选中起止日期后展示区间内所有符合条件的数据
  • 修复表格表头和内容顺序不匹配的问题
  • 下拉选项新增去重逻辑,避免相同站点重复展示
  • 修复useEffect无依赖项导致的重复请求问题
  • 后端新增参数化查询逻辑,避免SQL注入,优化大数据量下的筛选性能
  • 移除原有代码中的语法错误(如多余的enter code here片段)

内容的提问来源于stack exchange,提问作者Alpha Alimamy Kamara

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 01:24:03