ant-design / ant-design/pro-components

🐛[BUG]切换tab值并调用protable的tableFormRef.current.submit()方法,request回调执行次数和submit调用次数不一致,导致数据展示错误

Open
#7,533 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
4.8k
Forks
1.4k
Avg merge
10h 44m
Merged PRs (30d)
3

Description

### 🐛 bug 描述

切换tab值并调用protable的tableFormRef.current.submit()方法,request回调执行次数和submit调用次数不一致,导致数据展示错误

### 📷 复现步骤

进入页面先点击图1中,标号2的tab,然后**快速**切换:标号1tab,标号2tab,标号1tab,通过toolbar 定义的menu的onChange来手动设置menu的activeKey并调用tableFormRef.current.submit()方法,结果request只调用了两次,最后标号1的tab的现实的数据是标号2tab请求的数据结果,第三次的请求没有发出去

### 🏞 期望结果

期望的正确结果应该是每次手动调用tableFormRef.current.submit(),都会发起新的请求,tab展示对应请求的结果

### 💻 复现代码

import React, { useEffect, useState, useRef, useCallback } from 'react'
import PropTypes from 'prop-types'
import { Button } from 'antd'
import { decamelizeKeys } from 'humps'
import { get, throttle } from 'lodash'
import { CheckPerm } from 'permissions'
import qs from 'query-string'
import ProTable from '@ant-design/pro-table'
import { compose } from '@bit/redine'
import { transformTableQuery } from '@kfe/ecom-antd'
import { withUrlQuery } from '@kfe/ecom-hocs'
import common from 'modules/common'
import {
COMMISSION_TAB,
COMMISSION_TAB_MAP,
COMMISSION_STATUS
} from '../../../constans'
import { transformDate, caculateDate } from '../../../utils'
import CheckoutDate from '../components/checkoutDate'
import getColumns from '../components/columns'
import useTagColumns from '../components/useTagColumns'
import commission from '../modules/commission'
import CommissionTableConfig from './CommissionTableConfig'

// 操作状态-处理中
const PENDING_STTAUS = 2
let globalIndex1 = 0
const CommisionList = ({
loadCommissionList,
getTeamList,
isLoadingCommisionList,
downloadCommissionList,
getCommisionTags,
changeStatus
}) => {
const [selectedRowKeys, setSelectedRowKeys] = useState([])
const [activeTabKey, setActiveTabKey] = useState(COMMISSION_TAB_MAP.CHECK)
// 业务团队
const [teamList, setTeamList] = useState([])
const tableFormRef = useRef()
const tableListRef = useRef()

// 备注:审核 / 批量审核 / 结算 / 批量结算 / tab 切换
const reloadTable = useCallback(() => {
setSelectedRowKeys([])
tableFormRef.current.submit()
}, [])

// 标签搜索 & 标签组名称
const { getTagColumns, tagGroupNames } = useTagColumns(getCommisionTags)

// 处理标签参数
const handelTagParam = useCallback(
(params = {}) => {
tagGroupNames.forEach((groupName) => {
const tagMap = params[groupName]
if (!tagMap) return
const tags = Object.keys(tagMap).reduce((pre, name) => {
const tagList = Array.isArray(tagMap[name])
? tagMap[name].map((tag) => `${name}__${tag}`)
: []
return [...pre, ...tagList]
}, [])
params[`edu_${groupName}`] = tags.join(',')

delete params[groupName]
})
return params
},
[tagGroupNames]
)

// 处理 form 表单参数
const handleParam = (params = {}) => {
return decamelizeKeys(
transformTableQuery({
...handelTagParam(params),
commission_group_status: COMMISSION_STATUS[activeTabKey],
...transformDate(
params.commission_group_date_range?.[0],
params.commission_group_date_range?.[1]
)
})
)
}

// 携带标签筛选信息更新分佣状态
const changeStatusWithTag = useCallback(
(query, callback) => {
const params = {}
tagGroupNames.forEach((name) => {
params[name] = tableFormRef?.current?.getFieldValue(name)
})
changeStatus({ ...query, query_param: handelTagParam(params) }, callback)
},
[changeStatus, handelTagParam, tagGroupNames]
)

const handelDownload = throttle(
() => {
const fieldsValue = tableFormRef?.current?.getFieldsValue()
const param = {
data_type: 1,
// 所有内容都处理成字符串
query_param: JSON.stringify(
qs.parse(
qs.stringify(
handleParam({
...fieldsValue,
...caculateDate(
fieldsValue.commission_group_date,
'commission_group_date',
fieldsValue
)
})
)
)
)
}
downloadCommissionList(param)
},
3000,
{ trailing: false }
)

// 是否展示不结算原因
const showReason = [
COMMISSION_TAB_MAP.CHECKOUT,
COMMISSION_TAB_MAP.HISTORY
].includes(activeTabKey)

// 是否展示操作
const showOperation = [
COMMISSION_TAB_MAP.CHECK,
COMMISSION_TAB_MAP.CHECKOUT
].includes(activeTabKey)

// 是否展示结算时间选择 [当期结算,下期结算]
const showSelection = [
COMMISSION_TAB_MAP.CHECK,
COMMISSION_TAB_MAP.CHECKOUT
].includes(activeTabKey)

// 是否展示 「操作状态列」
const showOperationStatus = [
COMMISSION_TAB_MAP.CHECK,
COMMISSION_TAB_MAP.CHECKOUT
].includes(activeTabKey)

// 固定展示列
/**
* 「未结算-待审核」固定:分佣信息、操作状态、操作
* 「未结算」固定:分佣信息、分佣状态、操作状态、操作
* 历史结算」固定:分佣信息、分佣状态
*/
const columns = [
...getColumns({ teamList, showOperationStatus }),
...getTagColumns(tableFormRef),
{
title: '结算时间',
colSize: 4,
dataIndex: 'commission_group_date',
hideInTable: true,
renderFormItem: ({ ...props }) => (

),
search: {
transform: caculateDate
}
},
showReason && {
title: '不结算原因',
dataIndex: 'commission_group_info',
hideInSearch: true,
render: (value) => value?.no_settle_reason || '-'
},
showOperation && {
title: '操作',
dataIndex: 'commission_group_info.commission_group_id',
hideInSearch: true,
width: 100,
render(id, record) {
const { commission_group_info: info } = record
const isPending = get(info, 'op_status') === PENDING_STTAUS
const commisonStatus = get(info, 'commission_group_status')
const ops = CommissionTableConfig[activeTabKey]?.operations || []
const operations =
typeof ops === 'function' ? ops({ status: commisonStatus }) : ops
return (


{operations.map((item) => {
if (item.perms && !CheckPerm(item.perms)) return null

return (

item.onClick(record, {
op: changeStatusWithTag,
cb: reloadTable
})
}
>
{typeof item.title === 'function'
? item.title(record)
: item.title}

)
})}


)
}
}
]
.filter(Boolean)
.map((v) => ({
...v,
fixed:
CommissionTableConfig[activeTabKey].fixedConfig?.includes(v.title) &&
'right'
}))

const toolBarRender = useCallback(() => {
return CommissionTableConfig[activeTabKey].toolBarRender?.map((item) =>
item.perms && !CheckPerm(item.perms) ? null : (

item.onClick(selectedRowKeys, {
op: changeStatusWithTag,
cb: reloadTable
})
}
>
{item.title}

)
)
}, [activeTabKey, selectedRowKeys, changeStatusWithTag, reloadTable])

useEffect(() => {
getTeamList().then((data) => {
setTeamList(data)
})
}, [getTeamList])

const onTabsChange = useCallback(
(activeKey) => {
globalIndex1++
setActiveTabKey(activeKey)
reloadTable()
},
[reloadTable]
)

return (

get(record, 'commission_group_info.commission_group_id')
}
loading={isLoadingCommisionList}
search={{
span: 8,
labelWidth: 150,
defaultCollapsed: false,
collapseRender: () => null,
optionRender: (searchConfig, formProps, dom) => [
...dom,

导出

]
}}
scroll={{ x: 'max-content' }}
rowSelection={{
selectedRowKeys,
onChange: (keys) => setSelectedRowKeys(keys),
getCheckboxProps: (record) => {
return {
disabled:
get(record, 'commission_group_info.op_status') === PENDING_STTAUS // Column configuration not to be checked
}
}
}}
debounceTime={500}
formRef={tableFormRef}
form={{
labelAlign: 'right'
}}
toolbar={{
menu: {
type: 'tab',
activeKey: activeTabKey,
items: COMMISSION_TAB,
onChange: onTabsChange
}
}}
toolBarRender={toolBarRender}
options={false}
columns={columns}
request={async (params) => {
const curIndex = globalIndex1
const {
success,
data: { items = [], pagination: { total = 0 } = {} } = {}
} = await loadCommissionList(handleParam(params))
if (curIndex === globalIndex1) {
//快速切换tab导致数据错乱,通过变量控制是否设置返回数据
tableListRef.current = {
items,
total
}
}
return {
data: success ? tableListRef.current.items : [],
success: true,
total: success ? tableListRef.current.total : 0
}
}}
/>
)
}

CommisionList.propTypes = {
isLoadingCommisionList: PropTypes.bool,
loadCommissionList: PropTypes.func,
getTeamList: PropTypes.func,
downloadCommissionList: PropTypes.func,
getCommisionTags: PropTypes.func,
changeStatus: PropTypes.func
}

export default compose(commission, common, withUrlQuery)(CommisionList)

`

### © 版本信息

- ProComponents 版本: [e.g. 4.21.1]
- umi 版本
- 浏览器环境
- 开发环境 [e.g. mac OS]

### 🚑 其他信息

Contributor guide

Open the contributing guide

Research direction

Start with the ProTable request callback, formRef.submit(), and toolbar menu onChange paths shown in the reproduction. Reproduce rapid tab switches and inspect request completion ordering; done means every submit issues a request and the displayed data matches the active tab.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.