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

material-table onRowUpdate后数据库更新成功但表格未同步加载问题

Material-Table远程数据更新后表格不刷新问题

我用material-table结合远程数据,通过API从数据库取数,配置了onRowAdd和onRowUpdate编辑功能。现在遇到的问题是:更新行数据后,数据库已经成功更新,但表格必须刷新浏览器才会显示新数据。查服务器日志发现,material-table在后端更新完成前就触发了表格刷新,所以拿到的还是旧数据。推测是onRowUpdate返回的Promise还没完成,表格就发起了远程数据查询。

我的疑问:

  • 怎么让material-table等onRowUpdate的Promise完成后再刷新表格?
  • onRowAdd功能正常,新增行能直接显示,是不是material-table对onRowAdd的处理逻辑不一样?

另外,要是在API获取数据前留时间让更新请求完成,表格就能正确显示新数据,这也验证了是异步刷新导致的问题。


代码示例

<MaterialTable
    style={{backgroundColor: 'rgb(226, 231, 235)'}}
    icons={tableIcons}
    columns={tableColumns}
    data={query => 
      new Promise((resolve, reject) => {
        axios.get( props.apiURL + "menu-groups", {
          headers: {"Content-Type": "application/json",
                    "Request-ID": transactionId,
                    "Source-System": SOURCE_SYSTEM,
                    "Authorization": "Bearer " + someToken}
              }
          )
          .then(response => {
            props.onChange(response.data);

            resolve({
              data: response.data,
              page: null,
              totalCount: response.data.length
            });
          })
          .catch(error => { 
              console.error(error);
              reject(error);
          })
          
          setTransactionId(uuid());
      })
    }
    title="Menu Groups"
    
    editable={{
        onRowAdd: (newData) =>
          new Promise<void>((resolve, reject) => {
            setTimeout(() => {
              axios.post(props.apiURL + "menu-groups", JSON.stringify(newData), {
                  headers: {"Content-Type": "application/json",
                            "Request-ID": transactionId,
                            "Source-System": SOURCE_SYSTEM,
                            "Authorization": "Bearer " + someToken}
                }
              )
              .then(response => {
                resolve();
              })
              .catch(error => { 
                console.error(error);
                reject(error);
              })
                
              setTransactionId(uuid());
            }, 1000);
        }),
        onRowUpdate: (newData, oldData) =>
          new Promise<void>((resolve, reject) => {
            setTimeout(() => {
              axios.put(props.apiURL + "menu-groups" + "/" + newData.id, JSON.stringify(newData), {
                  headers: {"Content-Type": "application/json",
                            "Request-ID": transactionId,
                            "Source-System": SOURCE_SYSTEM,
                            "Authorization": "Bearer " + someToken
                }
              )
              .then(response => {
                resolve();
              })
              .catch(error => { 
                console.error(error);
                reject(error);
              })
                
              setTransactionId(uuid());
            }, 1000);
        }),
        onRowDelete: (oldData) =>
        new Promise<void>((resolve, reject) => {
            setTimeout(() => {
              axios.delete(props.apiURL + "menu-groups" + "/" + oldData.id, {
                headers: {"Content-Type": "application/json",
                          "Request-ID": transactionId,
                          "Source-System": SOURCE_SYSTEM,
                          "Authorization": "Bearer " + someToken}
              }
            )
            .then(response => {
              resolve();
            })
            .catch(error => { 
                console.error(error);
                reject(error);
            })
               
            setTransactionId(uuid());
          }, 1000);
        })
    }}

    />

问题解答

1. 让material-table等待onRowUpdate完成后再刷新的方案

核心问题是你在axios请求完成前就执行了setTransactionId(uuid()),甚至提前resolve了Promise,导致表格触发刷新时后端更新还没完成。需要确保Promise只有在后端请求完全成功后才结束,同时调整setTransactionId的执行时机:

修改onRowUpdate逻辑

onRowUpdate: (newData, oldData) =>
  new Promise<void>((resolve, reject) => {
    // 移除不必要的setTimeout,避免人为延迟
    axios.put(props.apiURL + "menu-groups/" + newData.id, JSON.stringify(newData), {
        headers: {
          "Content-Type": "application/json",
          "Request-ID": transactionId,
          "Source-System": SOURCE_SYSTEM,
          "Authorization": "Bearer " + someToken
        }
    })
    .then(response => {
      setTransactionId(uuid()); // 后端更新成功后再更新transactionId
      resolve(); // 此时再通知表格可以触发刷新
    })
    .catch(error => { 
      console.error(error);
      reject(error);
    })
}),

修正data回调中的时序问题

原代码中setTransactionId在axios.get发起后立即执行,会导致当前请求用的transactionId被提前修改,引发时序错误,需要移到请求完成后:

data={query => 
  new Promise((resolve, reject) => {
    axios.get( props.apiURL + "menu-groups", {
      headers: {
        "Content-Type": "application/json",
        "Request-ID": transactionId,
        "Source-System": SOURCE_SYSTEM,
        "Authorization": "Bearer " + someToken
      }
    })
    .then(response => {
      props.onChange(response.data);
      resolve({
        data: response.data,
        page: null,
        totalCount: response.data.length
      });
      setTransactionId(uuid()); // 请求完成后再更新transactionId
    })
    .catch(error => { 
      console.error(error);
      reject(error);
      setTransactionId(uuid()); // 失败场景也更新
    })
  })
}

2. onRowAdd正常的原因

material-table对onRowAdd的处理逻辑确实不同:当你完成onRowAdd的Promise后,它会先把新数据临时添加到本地表格缓存,然后再触发远程数据刷新。如果刷新后的返回数据包含这条新记录,就会替换本地缓存;如果没包含,也会保留本地缓存,所以你会看到新增行直接显示。

而onRowUpdate没有本地缓存更新的逻辑,完全依赖远程数据刷新获取最新行数据。当你的更新请求还没完成,表格就发起刷新,拿到的还是旧数据,自然看不到更新效果。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 09:49:50