如何阻止被react-query包裹的antd Collapse组件在refetchInterval触发时重置状态
问题根因
该现象的核心原因是refetchInterval触发数据重新拉取后,react-query的查询状态更新会触发对应组件树重渲染,若你的Collapse折叠状态未脱离渲染周期做持久化,或组件在重渲染流程中被卸载再重建,就会回到初始的关闭状态。
解决方案
你可以根据自己的业务场景选择以下任意一种方案修复:
- 将Collapse的展开状态提升到不受react-query查询结果影响的上层作用域存储
使用useState声明activeKey受控状态时,不要将初始值和查询结果强绑定,也不要在查询更新后强制覆盖activeKey的值,保证状态只在用户点击折叠面板时变更。 - 避免Collapse组件在查询过程中被卸载
不要将Collapse写在查询加载判断的分支外(例如if(isLoading) return <Loading />后返回Collapse),加载状态放在Collapse内部渲染即可;也可以给Collapse设置固定的key属性,避免React对组件进行不必要的卸载重建。 - 采用非受控模式使用Collapse
若不需要通过代码控制折叠状态,直接用defaultActiveKey设置初始状态即可,只要组件不被卸载,用户手动操作的展开状态会由组件内部自行保留,不会被重渲染重置。
代码示例
import { Collapse, Skeleton } from 'antd' import { useQuery } from '@tanstack/react-query' const Demo = () => { // 折叠状态独立存储,不随查询结果重置 const [activeKey, setActiveKey] = useState([]) const { data, isLoading } = useQuery({ queryKey: ['yourQueryKey'], queryFn: fetchYourData, refetchInterval: 3000 // 你的轮询间隔 }) return ( <Collapse activeKey={activeKey} onChange={setActiveKey} key="static-collapse-key" // 固定key避免组件重挂载 > <Collapse.Panel header="面板标题" key="panel1"> {/* 加载态放在面板内部,不影响Collapse本身的渲染 */} {isLoading ? <Skeleton active paragraph={{ rows: 3 }} /> : data?.panelContent} </Collapse.Panel> </Collapse> ) }
内容的提问来源于stack exchange,提问作者Errand
相关产品推荐
相关产品推荐

