8
8
Fragment as Signal ,
9
9
SkipRender ,
10
10
Slot ,
11
+ _jsxSorted ,
11
12
component$ ,
12
13
h ,
13
14
jsx ,
@@ -28,7 +29,8 @@ import { QError } from '../shared/error/error';
28
29
import { ErrorProvider } from '../../testing/rendering.unit-util' ;
29
30
import * as qError from '../shared/error/error' ;
30
31
import { QContainerValue } from '../shared/types' ;
31
- import { QContainerAttr } from '../shared/utils/markers' ;
32
+ import { OnRenderProp , QContainerAttr } from '../shared/utils/markers' ;
33
+ import { vnode_getParent , vnode_getProp , vnode_locate } from '../client/vnode' ;
32
34
33
35
const debug = false ; //true;
34
36
Error . stackTraceLimit = 100 ;
@@ -1991,6 +1993,105 @@ describe.each([
1991
1993
) ;
1992
1994
} ) ;
1993
1995
1996
+ it ( 'should reexecute entire component without key' , async ( ) => {
1997
+ const Child = component$ ( ( props : { text : string } ) => {
1998
+ const text = useSignal ( '' ) ;
1999
+ useTask$ ( ( ) => {
2000
+ text . value = props . text ;
2001
+ } ) ;
2002
+ return < div > { text . value } </ div > ;
2003
+ } ) ;
2004
+
2005
+ const Cmp = component$ ( ( ) => {
2006
+ const toggle = useSignal ( true ) ;
2007
+
2008
+ return (
2009
+ < >
2010
+ < button onClick$ = { ( ) => ( toggle . value = ! toggle . value ) } > </ button >
2011
+ { /* no key for both components */ }
2012
+ { toggle . value ? jsx ( Child , { text : 'Hello' } , null ) : jsx ( Child , { text : 'World' } , null ) }
2013
+ </ >
2014
+ ) ;
2015
+ } ) ;
2016
+
2017
+ const { vNode, document } = await render ( < Cmp /> , { debug } ) ;
2018
+ expect ( vNode ) . toMatchVDOM (
2019
+ < Component ssr-required >
2020
+ < Fragment ssr-required >
2021
+ < button > </ button >
2022
+ < Component ssr-required >
2023
+ < div >
2024
+ < Signal ssr-required > Hello</ Signal >
2025
+ </ div >
2026
+ </ Component >
2027
+ </ Fragment >
2028
+ </ Component >
2029
+ ) ;
2030
+ await trigger ( document . body , 'button' , 'click' ) ;
2031
+ expect ( vNode ) . toMatchVDOM (
2032
+ < Component ssr-required >
2033
+ < Fragment ssr-required >
2034
+ < button > </ button >
2035
+ < Component ssr-required >
2036
+ < div >
2037
+ < Signal ssr-required > World</ Signal >
2038
+ </ div >
2039
+ </ Component >
2040
+ </ Fragment >
2041
+ </ Component >
2042
+ ) ;
2043
+ } ) ;
2044
+
2045
+ it ( 'should remove component with null key when it is compared with fragment with null key' , async ( ) => {
2046
+ const InnerCmp = component$ ( ( ) => {
2047
+ return < div > InnerCmp</ div > ;
2048
+ } ) ;
2049
+
2050
+ const Cmp = component$ ( ( ) => {
2051
+ const toggle = useSignal ( true ) ;
2052
+
2053
+ return (
2054
+ < >
2055
+ < button onClick$ = { ( ) => ( toggle . value = ! toggle . value ) } > </ button >
2056
+ { toggle . value ? (
2057
+ < InnerCmp key = { null } />
2058
+ ) : (
2059
+ < Fragment key = { null } >
2060
+ < h1 > Test</ h1 >
2061
+ </ Fragment >
2062
+ ) }
2063
+ </ >
2064
+ ) ;
2065
+ } ) ;
2066
+
2067
+ const { vNode, document, container } = await render ( < Cmp /> , { debug } ) ;
2068
+ expect ( vNode ) . toMatchVDOM (
2069
+ < Component ssr-required >
2070
+ < Fragment ssr-required >
2071
+ < button > </ button >
2072
+ < Component ssr-required >
2073
+ < div > InnerCmp</ div >
2074
+ </ Component >
2075
+ </ Fragment >
2076
+ </ Component >
2077
+ ) ;
2078
+ await trigger ( document . body , 'button' , 'click' ) ;
2079
+
2080
+ expect ( vNode ) . toMatchVDOM (
2081
+ < Component ssr-required >
2082
+ < Fragment ssr-required >
2083
+ < button > </ button >
2084
+ < Fragment ssr-required >
2085
+ < h1 > Test</ h1 >
2086
+ </ Fragment >
2087
+ </ Fragment >
2088
+ </ Component >
2089
+ ) ;
2090
+ const h1Element = vnode_locate ( container . rootVNode , document . querySelector ( 'h1' ) ! ) ;
2091
+
2092
+ expect ( vnode_getProp ( vnode_getParent ( h1Element ) ! , OnRenderProp , null ) ) . toBeNull ( ) ;
2093
+ } ) ;
2094
+
1994
2095
describe ( 'regression' , ( ) => {
1995
2096
it ( '#3643' , async ( ) => {
1996
2097
const Issue3643 = component$ ( ( ) => {
0 commit comments