React Hooks中handleEvent函数内无法获取DateRangePicker更新后state如何解决
问题原因
React 的 useState 更新属于异步批量操作,在事件回调函数中调用 setFromDate、setToDate 之后,当前函数作用域内的 fromDate、toDate 仍属于本次渲染闭包缓存的旧值,不会立刻同步更新,因此你在函数内部读取到的永远是上一次的选中结果。
解决方案
你可以直接使用事件回调返回的最新日期值构造请求,不需要依赖 state 更新后的结果,调整后的代码如下:
import React, { useState } from "react"; import DateRangePicker from "react-bootstrap-daterangepicker"; import "bootstrap-daterangepicker/daterangepicker.css"; import moment from "moment"; import DataProvider from "context/DataContext"; import ApiService from "services/api"; export default function DatePicker() { const [fromDate, setFromDate] = useState(new Date()); const [toDate, setToDate] = useState(new Date()); const range = { Today: [moment(), moment()], Yesterday: [moment().subtract(1, "days"), moment().subtract(1, "days")], "Last 7 Days": [moment().subtract(6, "days"), moment()], "Last 30 Days": [moment().subtract(29, "days"), moment()], "This Month": [moment().startOf("month"), moment().endOf("month")], "Last Month": [ moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month"), ], "Last Year": [ moment().subtract(1, "year").startOf("year"), moment().subtract(1, "year").endOf("year"), ], }; const handleEvent = (event, picker) => { const newStart = picker.startDate._d; const newEnd = picker.endDate._d; // 更新state用于页面显示 setFromDate(newStart); setToDate(newEnd); // 直接用最新的日期构造请求 const requestData = { metrics: ["views"], project_id: "abc", date_range: { start_at: newStart, end_at: newEnd }, }; ApiService.create({ requestData }).then((onSuccess) => { console.log(onSuccess); }); }; return ( <DateRangePicker ranges={range} alwaysShowCalendars={false} onEvent={handleEvent} > <button> {moment(fromDate).format("ll")} to {moment(toDate).format("ll")} </button> </DateRangePicker> ); }
可选方案
如果你有其他逻辑必须依赖更新后的 state 执行,可以用 useEffect 监听日期变化触发请求:
// 组件内新增useEffect useEffect(() => { const requestData = { metrics: ["views"], project_id: "abc", date_range: { start_at: fromDate, end_at: toDate }, }; ApiService.create({ requestData }).then((onSuccess) => { console.log(onSuccess); }); }, [fromDate, toDate])
内容的提问来源于stack exchange,提问作者Gurupal singh
相关产品推荐
相关产品推荐

