@@ -636,4 +636,85 @@ describe('Table.Virtual', () => {
636636 top : 200 ,
637637 } ) ;
638638 } ) ;
639+
640+ it ( 'should not crash when pageSize shrinks after scrolled to bottom (rowSpan)' , async ( ) => {
641+ const errSpy = vi . spyOn ( console , 'error' ) . mockImplementation ( ( ) => { } ) ;
642+ const tblRef = React . createRef < Reference > ( ) ;
643+
644+ const makeData = ( len : number ) =>
645+ Array . from ( { length : len } ) . map ( ( _ , id ) => ( {
646+ id,
647+ firstName : `First_${ id . toString ( 16 ) } ` ,
648+ lastName : `Last_${ id . toString ( 16 ) } ` ,
649+ age : 20 + ( id % 30 ) ,
650+ address : `Address_${ id } ` ,
651+ } ) ) ;
652+
653+ const data = makeData ( 10000 ) ;
654+
655+ const columns = [
656+ { dataIndex : 'id' , width : 100 , fixed : 'left' } ,
657+ { dataIndex : 'firstName' , width : 140 , fixed : 'left' } ,
658+ { dataIndex : 'lastName' , width : 140 } ,
659+ {
660+ dataIndex : 'group' ,
661+ width : 160 ,
662+ render : ( _ : any , record : any ) => `Group ${ Math . floor ( record . id / 4 ) } ` ,
663+ onCell : ( record : any ) => ( {
664+ rowSpan : record . id % 4 === 0 ? 4 : 0 ,
665+ } ) ,
666+ } ,
667+ {
668+ dataIndex : 'age' ,
669+ width : 120 ,
670+ onCell : ( record : any ) => ( {
671+ colSpan : record . id % 4 === 0 ? 2 : 1 ,
672+ } ) ,
673+ } ,
674+ {
675+ dataIndex : 'address' ,
676+ width : 220 ,
677+ onCell : ( record : any ) => ( {
678+ colSpan : record . id % 4 === 0 ? 0 : 1 ,
679+ } ) ,
680+ } ,
681+ ] ;
682+
683+ const renderTable = ( pageSize : number ) => (
684+ < VirtualTable
685+ ref = { tblRef }
686+ columns = { columns as any }
687+ rowKey = "id"
688+ scroll = { { x : 900 , y : 200 } }
689+ data = { data . slice ( 0 , pageSize ) }
690+ />
691+ ) ;
692+
693+ const { rerender } = render ( renderTable ( 200 ) ) ;
694+
695+ await waitFakeTimer ( ) ;
696+
697+ // 模拟滚到底
698+ act ( ( ) => {
699+ tblRef . current ?. scrollTo ?.( { top : 10 ** 10 } ) ;
700+ } ) ;
701+
702+ await waitFakeTimer ( ) ;
703+
704+ // 切到 pageSize=10(slice 模拟分页)
705+ expect ( ( ) => {
706+ rerender ( renderTable ( 10 ) ) ;
707+ } ) . not . toThrow ( ) ;
708+
709+ // flush timers to cover transient render
710+ vi . runAllTimers ( ) ;
711+ await waitFakeTimer ( ) ;
712+
713+ // 不应出现 record undefined 相关错误
714+ const errorText = errSpy . mock . calls . map ( args => String ( args [ 0 ] ?? '' ) ) . join ( '\n' ) ;
715+ expect ( errorText ) . not . toContain ( 'Cannot read properties of undefined' ) ;
716+ expect ( errorText ) . not . toContain ( "reading 'record'" ) ;
717+
718+ errSpy . mockRestore ( ) ;
719+ } ) ;
639720} ) ;
0 commit comments