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

React中MaterialTable首次加载Redux远程数据失败问题求助

Hey there! Let's dig into why your MaterialTable isn't loading data properly with Redux for server-side pagination. I've spotted the core issue and put together a fixed solution for you.

The Root Problem

Your current code calls getVehichles in the MaterialTable data function and immediately resolves the promise. But Redux's async data flow takes time—when you resolve, the this.props.vehichles.rows hasn't been updated yet (the API request is still in flight). Plus, the data function runs on initial render before Redux has finished initializing, so you're loading empty data by default.

Fixed Solution with Step-by-Step Changes

Let's restructure the code to sync MaterialTable's pagination state with Redux properly:

1. Updated VehicleList Component (Fixed Spelling & Logic)

import React, { Component } from "react";
import Button from "@material-ui/core/Button";
import Grid from "@material-ui/core/Grid";
import Box from "@material-ui/core/Box";
import { connect } from "react-redux";
import MaterialTable from "material-table";
import { getVehicles } from "../../store/actions/vehicleActions";

class VehicleActionButtons extends Component {
  constructor(props) {
    super(props);
    this.tableRef = React.createRef();
    // Track pagination state locally to sync with table
    this.state = {
      currentPage: 0,
      pageSize: 10 // Match MaterialTable's default page size
    };
  }

  componentDidMount() {
    // Load initial data when component mounts
    const { currentPage, pageSize } = this.state;
    this.props.getVehicles({ page: currentPage, pageSize });
  }

  // Trigger data fetch when page changes
  handlePageChange = (newPage) => {
    this.setState({ currentPage: newPage }, () => {
      const { currentPage, pageSize } = this.state;
      this.props.getVehicles({ page: currentPage, pageSize });
    });
  };

  // Reset page to 0 and fetch data when rows per page changes
  handleRowsPerPageChange = (newPageSize) => {
    this.setState({ pageSize: newPageSize, currentPage: 0 }, () => {
      const { currentPage, pageSize } = this.state;
      this.props.getVehicles({ page: currentPage, pageSize });
    });
  };

  refreshTableData = () => {
    if (this.tableRef.current) {
      this.tableRef.current.onQueryChange();
    }
  };

  render() {
    const { vehicles } = this.props;
    const { currentPage, pageSize } = this.state;

    return (
      <Box m={6}>
        <Grid container>
          <Grid item xs>
            <Box m={2}>
              <MaterialTable
                tableRef={this.tableRef}
                columns={vehicles.columns}
                // Resolve data directly from Redux props (updated when state changes)
                data={() =>
                  Promise.resolve({
                    data: vehicles.rows,
                    page: currentPage,
                    totalCount: vehicles.totalCount
                  })
                }
                title="Vehicle List"
                options={{
                  pagination: true,
                  pageSize,
                  pageSizeOptions: [5, 10, 20],
                  serverSide: true
                }}
                // Bind pagination callbacks to trigger Redux actions
                onChangePage={this.handlePageChange}
                onChangeRowsPerPage={this.handleRowsPerPageChange}
                // Show loading state while data is being fetched
                isLoading={!vehicles.loaded}
              />
            </Box>
          </Grid>
        </Grid>
      </Box>
    );
  }
}

const mapStateToProps = (state) => {
  return {
    vehicles: state.vehicle
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    getVehicles: (query) => dispatch(getVehicles(query))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(VehicleActionButtons);

2. Updated Action Code (Cleaner Async Logic)

import axios from 'axios';
export const getVehicles = (query) => {
  return async (dispatch) => {
    dispatch({ type: "GETTING_VEHICLES_LIST"});
    try {
      // Use template literals for cleaner URL construction
      const url = `http://my-json-server.typicode.com/mksrivastava/zwe/rows?_limit=${query.pageSize}&_page=${query.page + 1}`;
      const resp = await axios.get(url);
      dispatch({ 
        type: "GET_VEHICLES_LIST", 
        data: resp.data,
        totalCount: +resp.headers['x-total-count']
      });
    } catch (error) {
      dispatch({ 
        type: "GET_VEHICLES_LIST_ERROR", 
        error: error.message || "Unexpected Error!!!" 
      });
    }
  };
}

3. Updated Reducer Code (Spelling Fixes & Clear State Updates)

const initState = {
  rows: [],
  columns: [
    { title: "Vehicle No", field: "vehicleNo" },
    { title: "Date of Reg", field: "dateOfReg", type: "date" },
    { title: "Status of Reg", field: "statusOfReg" },
    { title: "Engine Type", field: "EngineType" },
    { title: "Modal Year", field: "year" },
  ],
  totalCount: 0,
  loaded: false,
  error: null
};

const vehicleReducer = (state = initState, action) => {
  switch (action.type) {
    case "GETTING_VEHICLES_LIST":
      return { ...state, loaded: false, error: null };
    case "GET_VEHICLES_LIST":
      return { 
        ...state, 
        rows: action.data, 
        totalCount: action.totalCount, 
        loaded: true 
      };
    case "GET_VEHICLES_LIST_ERROR":
      return { ...state, loaded: true, error: action.error };
    default:
      return state;
  }
};

export default vehicleReducer;

Key Improvements

  • Unified Spelling: Fixed vehichle → vehicle everywhere to avoid state mapping bugs.
  • Controlled Pagination: Used MaterialTable's onChangePage and onChangeRowsPerPage to trigger data fetches, making the flow predictable.
  • Loading Feedback: Added isLoading to show users when data is being fetched.
  • Cleaner Async Code: Used async/await in actions for readability, and passed only necessary data to the reducer.

This setup ensures your table loads initial data on mount, updates automatically when Redux state changes, and syncs perfectly with pagination controls.

内容的提问来源于stack exchange,提问作者Manish Kumar Srivastava

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:28:13