更新最初来自远程数据的单个物料表行

如何解决更新最初来自远程数据的单个物料表行

我有一个React材料表。我希望其中一列是我的自定义<DatePicker/>组件,用户可以在其中为该行分配计划的日期。 表格currentley可以远程获取数据。

使用<DatePicker/>组件并选择日期时,我不希望整个表从远程源重新获取数据。相反,我希望<DatePicker/> onChange处理程序修改表中的当前数据(我将日期设置为该行的行)。

有没有办法进入材料表数据存储并调用“ setData”函数,以便仅更新目标行?

通常,如果表的数据不是来自远程数据源,我只会调用自己的“ setData”函数,但是由于我利用了构建在远程数据选项中的物料表并使用过滤器,因此我无法做到这一点。

解决方法

当数据来自远程源时,我无法找到一种干净的方法来利用物料表的数据并更新行。但是,我能够提出一种可行的“ hacky”解决方案。

为此,我执行了以下操作:

  1. 创建了一个表以引用物料表并将其存储在我的Redux商店中。
  2. 创建本地组件状态以存储我以前的查询参数历史记录。
  3. 将MaterialTable上的data道具设置为自定义getData函数,该函数返回Promise,以命中后端api以获取表数据(所有行),或修改当前表数据,然后返回此新修改的数据。该函数使用tableRef.current.dataManager.getRenderState().data获取当前的MaterialTable数据。然后返回它的修改版本(如果需要)。
  4. 创建了一个小型组件(NextAction),该组件需要2个道具-来自MaterialTable的rowData和来自Redux商店的tableRef-呈现包含我的自定义操作按钮的列,将其单击以修改当前表数据。该组件还可以访问Redux存储中存储的物料表的tableRef。该组件(最终是一个按钮)利用tableRef上的onQueryChange()函数来手动强制对getData函数的调用。
  5. 在我的列定义中设置渲染键,以返回名为NextAction的组件。

这个想法是要有一个带有按钮的列。按下按钮后,该行的“当前状态”列将被修改,并且不会从api重新呈现表数据。

之所以起作用,是因为单击该按钮时将调用tableRef.current.onQueryChange()函数。因为组件的“数据”属性设置为自定义getData函数,所以在调用tableRef.current.onQueryChange()时,告诉MaterialTable调用data函数,该函数是我们在MaterialTable组件上设置的自定义getData函数。>

然后在此getData函数中,检查新查询参数是否与旧查询参数不同(因为查询参数也存储在本地状态)。如果它们相同,则检查getData查询参数是否具有nextState键。仅当从自定义按钮调用getData时,才存在nextState键。如果是这样,我们将使用tableRef来访问当前表数据,修改我们想要的行,然后返回新的tableData(仍包装在Promise中)。

以下是实现上述目标的示例代码:

import React,{ useContext } from 'react';
import { connect } from 'react-redux';
import axios from 'my/path/to/axios';

/*
  Custom Button  rendered in a column on the MaterialTable
  Takes a tableRef prop from the Redux Store.
  Note the onClick function that is called.
*/
const NextActionButton = connect(mapStateToPropsNextAction)(( props ) => {
  const tableRef = props.tableRef; // captured from redux store - tableRef from MaterialTable
  return (
    <Button
      disabled={false}
      variant="contained"
      color="secondary"
      size="large"
      onClick={(e) => {tableRef.current.onQueryChange({
        onNextAction: true,nextState: 'dispatched',row_id: props.rowData.tableData.id,})}}
      >
      Dispatch
    </Button>
  )
})

const MyComponent = ( props ) => {

  let tableRef = React.createRef()  // Create the tableRef
  props.setTableRef(tableRef)

  // Store the query history
  const [queryHist,setQueryHist] = React.useState({});

  // Custom function to return the table data either via api or from the old state with modifications
  const getData = (query,tableRef) => new Promise((resolve,reject) => {
    const queryParams = {
      filters: query.filters,orderBy: query.orderBy,orderDirection: query.orderDirection,page: query.page,pageSize: query.pageSize,search: query.search,}

    /*
    Here is the magic that allows us to update the current tableData state without hitting the api

    If the query is the same as before,then just return the same table without hitting api
    This occurs only when:
      1.) the user types the same filter
      2.) when the user wants to update a single row through the special update component in the update column
    */
    if (JSON.stringify(queryHist) === JSON.stringify(queryParams)) {
      // This is how we get MaterialTable's current table data. This is a list of objects,each object is a row.
      let newData = tableRef.current.dataManager.getRenderState().data; 
      if (query.onNextAction === true) {
        newData[query.row_id].current_state = query.nextState;
      }
      resolve({
        data: newData,page: tableRef.current.state.query.page,totalCount: tableRef.current.state.query.totalCount,})
    }

    setQueryHist(queryParams)  // Store query params in the local state for future comparison

    axios.get('/my_data_api',{
      params: queryParams
    }).then(response => {
        return resolve({
          data: response.data.data,page: response.data.page,totalCount: response.data.total_count,})
      }).catch(function (error) {
        console.log(error);
      })
  })

  const [columns] = React.useState([
    {
      title: "Record Id",field: "record_id",},{
      title: "Current State",field: "current_state",// This is the field we will be updating with the NextActionButton
    },{
      title: "Next Action",field: "placeholder",filtering: false,render: (rowData) =>  <NextActionButton rowData={rowData}/> // Render the custom button component
    },])

  return (
    <MaterialTable
      title="My Table Title"
      tableRef={tableRef}  // Assign the ref to MaterialTable
      data={
        (query) => getData(query,tableRef)
      }
      columns={columns}
      options={{
        filtering: true,debounceInterval: 600,paging: true,pageSize: 50,pageSizeOptions: [50,100,1000],emptyRowsWhenPaging: false,selection: true,}}
      .
      .
      .

    />
  )
}

// Redux stuff
const mapDispatchToProps = dispatch => {
  return {
    setTableRef: (tableRef) => dispatch({type: 'SET_TABLE_REF','ref': tableRef})
    .
    .
    .
  };
};

export default connect(null,mapDispatchToProps)(Workorders);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-