@@ -211,6 +211,95 @@ describe('Table.Virtual', () => {
211211 } ) ;
212212 } ) ;
213213
214+ it ( 'keeps force-rendered expanded content mounted across expand and collapse' , ( ) => {
215+ const onMount = vi . fn ( ) ;
216+ const onUnmount = vi . fn ( ) ;
217+
218+ class StatefulContent extends React . Component < unknown , { count : number } > {
219+ state = { count : 0 } ;
220+
221+ componentDidMount ( ) {
222+ onMount ( ) ;
223+ }
224+
225+ componentWillUnmount ( ) {
226+ onUnmount ( ) ;
227+ }
228+
229+ render ( ) {
230+ return (
231+ < button
232+ type = "button"
233+ className = "stateful-expanded-content"
234+ onClick = { ( ) => this . setState ( ( { count } ) => ( { count : count + 1 } ) ) }
235+ >
236+ { this . state . count }
237+ </ button >
238+ ) ;
239+ }
240+ }
241+
242+ const { container } = getTable ( {
243+ data : [ { name : 'name0' , age : 0 , address : 'address0' } ] ,
244+ expandable : {
245+ expandedRowRender : ( ) => < StatefulContent /> ,
246+ forceRender : true ,
247+ } ,
248+ } ) ;
249+
250+ const expandIcon = container . querySelector ( '.rc-table-row-expand-icon' ) ! ;
251+ const content = container . querySelector ( '.stateful-expanded-content' ) ! ;
252+
253+ expect ( onMount ) . toHaveBeenCalledTimes ( 1 ) ;
254+ expect ( onUnmount ) . not . toHaveBeenCalled ( ) ;
255+
256+ fireEvent . click ( expandIcon ) ;
257+ fireEvent . click ( content ) ;
258+ expect ( content ) . toHaveTextContent ( '1' ) ;
259+
260+ fireEvent . click ( expandIcon ) ;
261+ expect ( container . querySelector ( '.stateful-expanded-content' ) ) . toBe ( content ) ;
262+ expect ( onUnmount ) . not . toHaveBeenCalled ( ) ;
263+
264+ fireEvent . click ( expandIcon ) ;
265+ expect ( container . querySelector ( '.stateful-expanded-content' ) ) . toBe ( content ) ;
266+ expect ( content ) . toHaveTextContent ( '1' ) ;
267+ expect ( onMount ) . toHaveBeenCalledTimes ( 1 ) ;
268+ expect ( onUnmount ) . not . toHaveBeenCalled ( ) ;
269+ } ) ;
270+
271+ it ( 'does not duplicate force-rendered content for rowSpan overlay lines' , ( ) => {
272+ const expandedRowRender = vi . fn ( ( record : { name : string } ) => (
273+ < span data-expanded-record = { record . name } > { record . name } </ span >
274+ ) ) ;
275+ const data = [
276+ { name : 'name0' , age : 0 , address : 'address0' } ,
277+ { name : 'name1' , age : 1 , address : 'address1' } ,
278+ ] ;
279+ const { container } = getTable ( {
280+ data,
281+ columns : [
282+ {
283+ dataIndex : 'name' ,
284+ onCell : ( _ , index ) => ( {
285+ rowSpan : index === 0 ? 2 : 0 ,
286+ } ) ,
287+ } ,
288+ ] ,
289+ expandable : {
290+ expandedRowRender,
291+ forceRender : true ,
292+ } ,
293+ } ) ;
294+
295+ expect ( container . querySelector ( '.rc-table-row-extra' ) ) . toBeTruthy ( ) ;
296+ expect ( expandedRowRender ) . toHaveBeenCalledTimes ( 2 ) ;
297+ expect ( expandedRowRender ) . toHaveBeenNthCalledWith ( 1 , data [ 0 ] , 0 , 1 , false ) ;
298+ expect ( expandedRowRender ) . toHaveBeenNthCalledWith ( 2 , data [ 1 ] , 1 , 1 , false ) ;
299+ expect ( container . querySelectorAll ( '[data-expanded-record="name0"]' ) ) . toHaveLength ( 1 ) ;
300+ expect ( container . querySelectorAll ( '[data-expanded-record="name1"]' ) ) . toHaveLength ( 1 ) ;
301+ } ) ;
302+
214303 it ( 'applies expanded row class to tree rows' , ( ) => {
215304 const { container } = getTable ( {
216305 data : [
0 commit comments