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

React调用Django API获取两日期区间数据并在表格展示

React 前端日期范围筛选订单实现方案

现存问题梳理

  • 已完成全量订单拉取、日期选择器绑定,但未实现提交后的筛选逻辑
  • componentDidMount 中存在重复赋值orders的冗余代码,会覆盖接口返回的正确订单数据
  • 日期选择器同时传入selected和value属性会产生组件冲突
  • 未处理日期筛选的边界问题,容易漏掉起止日期当天的订单
  • 存在两个绑定同一提交事件的表单,交互逻辑冗余
  • 接口拉取用户数据时未给id字段赋值,头部用户ID展示为空

具体实现步骤

  • 调整state结构,新增filteredOrders字段专门存储当前要展示的订单数据,默认初始为空,拉取完全量数据后和全量订单保持一致
  • 删除componentDidMount里冗余的.then赋值逻辑,在fetchFarmerData拿到全量订单后,同时给orders和filteredOrders赋值,补全id字段的赋值
  • 完善handleSubmit逻辑,用已引入的moment做日期比对:把选中的开始日期转为当天0点,结束日期转为当天23:59:59,遍历全量订单,筛选出added_on在这个时间区间内的订单,赋值给filteredOrders
  • 调整表格渲染逻辑,遍历数据源从this.state.orders改为this.state.filteredOrders
  • 修复日期选择器属性冲突,删掉多余的value属性,合并重复的表单结构,把生成报告按钮放到日期筛选的同一个表单里
  • 可选优化:增加重置按钮,点击后恢复展示全量数据

关键修改代码

state 调整

state = {
    errorRes: false,
    errorMessage: "",
    btnMessage: 0,
    sendData: false,
    orders: [], // 存储全量原始订单
    filteredOrders: [], // 存储当前要展示的订单(筛选后/全量)
    startDate: moment().startOf('day').toDate(), // 默认开始日期为当天0点
    endDate: moment().endOf('day').toDate(), // 默认结束日期为当天23:59
    dataLoaded: false,
    formSubmitted: false,
    name: "",
    id: "",
    phone: "" // 补全原state缺失的phone字段,避免赋值警告
};

生命周期与数据拉取逻辑修改

// 删除componentDidMount中冗余的then回调
componentDidMount() {
    this.fetchFarmerData();
}

async fetchFarmerData() {
    var apihandler = new APIHandler();
    var farmerdata = await apihandler.fetchFarmerDetails(this.props.match.params.id);
    const { orders, name, phone, id } = farmerdata.data.data;
    this.setState({ 
        orders,
        filteredOrders: orders, // 默认展示全量数据
        name,
        phone,
        id, // 补全用户ID赋值
        dataLoaded: true 
    });
}

筛选提交逻辑实现

handleSubmit = (event) => {
    event.preventDefault();
    const { startDate, endDate, orders } = this.state;
    // 处理日期边界,避免漏选起止日期当天的数据
    const start = moment(startDate).startOf('day');
    const end = moment(endDate).endOf('day');

    // 前端过滤全量数据
    const filtered = orders.filter(order => {
        const orderTime = moment(order.added_on);
        return orderTime.isBetween(start, end, null, '[]'); // []参数表示包含起止时间边界
    });

    this.setState({
        filteredOrders: filtered,
        formSubmitted: true
    });
}

// 可选:重置筛选方法
handleReset = () => {
    this.setState({
        startDate: moment().startOf('day').toDate(),
        endDate: moment().endOf('day').toDate(),
        filteredOrders: this.state.orders,
        formSubmitted: false
    })
}

表单与表格渲染修改

合并重复表单,修复日期选择器属性问题:

<div className="dt-buttons">
    <a className="dt-button buttons-csv buttons-html5" tabIndex="0" aria-controls="DataTables_Table_1" href="#">
        <span>
        <ReactHTMLTableToExcel 
            className="btn btn-success"
            tabIndex="0" 
            aria-controls="DataTables_Table_1"
            table="DataTables_Table_1"
            filename="FarmerStatement"
            sheet="Sheet"
            buttonText="Excel"
        />
        </span>
    </a> 
    <a className="dt-button buttons-print" tabIndex="0" aria-controls="DataTables_Table_1" href="#" onClick={() => this.print()}>
        <span>Print</span>
    </a>
    <br/>
</div>

<div id="DataTables_Table_1_filter" className="dataTables_filter">
    <form onSubmit={this.handleSubmit}>
        <label>
            <i className="material-icons">date_range</i>Start Date:
                <DatePicker
                    selected={this.state.startDate}
                    className="form-control datepicker" 
                    name="startDate"
                    aria-controls="DataTables_Table_1"
                    onChange={this.handleStartDateChange}
                    dateFormat="dd/MM/yyyy"
                />
        </label>
        <br/>
        <label>
            <i className="material-icons">date_range</i>End Date:
                <DatePicker
                    selected={this.state.endDate}
                    className="form-control datepicker" 
                    name="endDate"
                    aria-controls="DataTables_Table_1"
                    onChange={this.handleEndDateChange}
                    dateFormat="dd/MM/yyyy"
                />
        </label>
        <button type="submit" className="btn btn-info" style={{marginLeft: '10px'}}>
            Generate Report
        </button>
        <button type="button" className="btn btn-default" style={{marginLeft: '5px'}} onClick={this.handleReset}>
            Reset
        </button>
    </form>    
</div>

修改表格遍历数据源,增加空状态提示:

<tbody>   
{this.state.filteredOrders.length === 0 && this.state.formSubmitted ? (
    <tr>
        <td colSpan="5" className="text-center">所选日期范围内无订单数据</td>
    </tr>
) : this.state.filteredOrders.map((farmer) => (
    <tr role="row" className="odd" key={farmer.id}>
        <td className="sorting_1">{farmer.id}</td>
        <td className="sorting_1">{farmer.customer.name}</td>
        <td className="sorting_1">{farmer.kgs}</td>
        <td className="sorting_1">{farmer.price}</td>
        <td className="sorting_1">{new Date(farmer.added_on).toLocaleString()}</td>
    </tr>
))}
</tbody>

注意事项

  • 上述前端筛选方案适合单页数据量千条以内的场景,如果总订单量过万,建议把起止日期作为参数传给后端,在接口层做筛选,性能更好
  • 用moment的isBetween方法搭配边界参数可以直接覆盖全天时间,不用手动转时间戳,能避免时区导致的筛选偏差
  • react-datepicker组件只需要传selected属性绑定值即可,重复传value会导致选值后视图不更新或者控制台报错

内容的提问来源于stack exchange,提问作者Ahmed Sereta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:57:08