React跨组件传递react-datepicker日期状态及API传参问题问询
问题根因
两个报错和功能失效都是API用法不匹配导致的:
react-datepicker的onSelect/onChange回调不会返回原生DOM event对象,第一个入参直接是选中的Date实例,写event.target.value自然会报target未定义- 路由跳转时直接把Date对象塞进URL模板,会被转成无意义的字符串;且仪表盘组件没有从路由参数里取日期值,也没有把日期拼到API请求地址里
- 现有Picker组件没有绑定提交触发逻辑,
handleSubmit函数根本不会被执行
分步修复方案
1. 修复Picker.js组件
首先修正日期回调的取值逻辑,去掉冗余的onSelect绑定,日期转成标准格式后再拼到路由参数里,补全提交触发逻辑:
import React, { useState } from "react"; import DatePicker from "react-datepicker"; import { useNavigate } from "react-router-dom" import "react-datepicker/dist/react-datepicker.css"; const Picker = () => { const navigate = useNavigate(); // 初始值按需设置,默认选当天就保留new Date() const [startDate, setStartDate] = useState(new Date()); // 选完日期直接跳转用这个逻辑,不需要单独提交按钮 const handleDateChange = (selectedDate) => { setStartDate(selectedDate); // 转成YYYY-MM-DD格式适配后端接口,避免URL参数异常 const formatDate = selectedDate.toISOString().split('T')[0]; navigate(`/guage/${formatDate}`); } // 如果需要手动点提交按钮再跳转,保留这个方法,同时在JSX里补表单和按钮 // const handleSubmit = (event) =>{ // event.preventDefault(); // const formatDate = startDate.toISOString().split('T')[0]; // navigate(`/guage/${formatDate}`) // } return ( {/* 选完直接跳就用这行 */} <DatePicker selected={startDate} onChange={handleDateChange} /> {/* 要手动提交就用下面的结构,替换上面的DatePicker单行 <form onSubmit={handleSubmit}> <DatePicker selected={startDate} onChange={(date) => setStartDate(date)} /> <button type="submit">查看仪表盘</button> </form> */} ); }; export default Picker
注意:如果后端要求的日期格式不是YYYY-MM-DD,自行修改格式化逻辑,保证URL里传的字符串和后端要求格式完全匹配即可
2. 修复DelayGuage.js组件
用useParams取路由里的date参数,把参数拼到API请求地址里,同时给react-query的queryKey加上date依赖,保证日期变化时自动重新拉取对应数据:
import React from "react"; import { Chart } from "react-google-charts"; import axios from "axios"; import { useQuery } from 'react-query'; import { useParams } from "react-router-dom"; // 把date作为参数传入请求方法 async function fetchPosts(date) { const {data} = await axios.get( // 直接把拿到的日期参数拼进URL `http://172.16.10.100:5004/reports/${date}/agencies` ); const parsedData = data.agencies[0].kpis.map((r) => [ "Delay Index", r.kpi_value * 100 ]); return [["Label", "Value"], ...parsedData]; } const DelayGuage = () => { // 取路由里的date参数 const { date } = useParams(); // 把date放进queryKey,日期变化时自动重新请求 const { data: chartData, isLoading, error } = useQuery( ['delayReport', date], () => fetchPosts(date), { // date不存在时不发无效请求 enabled: !!date } ); if (isLoading) return <div>加载中...</div> if (error) return <div>数据加载失败</div> return ( <Chart chartType="Gauge" width="100%" height="400px" data={chartData} options={{ redFrom: 90, redTo: 100, yellowFrom: 75, yellowTo: 90, minorTicks: 5, }} /> ) } export default DelayGuage;
注意:要保证路由配置里写了/guage/:date的动态路由规则,否则useParams拿不到date参数
校验要点
改完后按顺序验证:
- 打开日期选择器选日期,控制台不再报
event.target is undefined错误 - 选完日期后地址栏跳转到
/guage/xxxx-xx-xx格式的路径,日期格式和后端要求一致 - 仪表盘页面自动发起对应日期的API请求,返回数据后正常渲染图表
- 手动修改地址栏里的日期参数,页面会自动拉取新日期的数据重绘图表,不需要手动刷新
内容的提问来源于stack exchange,提问作者roastyroach
相关产品推荐
相关产品推荐

