File tree Expand file tree Collapse file tree 4 files changed +122
-6
lines changed
Expand file tree Collapse file tree 4 files changed +122
-6
lines changed Original file line number Diff line number Diff line change 1+ ## Inline Order
2+
3+
4+ <code src =" ../examples/inlineOrder.tsx " />
Original file line number Diff line number Diff line change 1+ import React , { version } from 'react' ;
2+ import Portal from '../../src' ;
3+ import './basic.less' ;
4+
5+ const Child = ( ) => {
6+ const divRef = React . useRef < HTMLPreElement > ( null ) ;
7+
8+ React . useEffect ( ( ) => {
9+ const path : Element [ ] = [ ] ;
10+
11+ for ( let cur : HTMLElement = divRef . current ; cur ; cur = cur . parentElement ) {
12+ path . push ( cur ) ;
13+ }
14+
15+ console . log ( 'Path:' , path ) ;
16+ } , [ ] ) ;
17+
18+ return (
19+ < pre ref = { divRef } style = { { border : '1px solid red' } } >
20+ < p > Hello Child { version } </ p >
21+ </ pre >
22+ ) ;
23+ } ;
24+
25+ export default ( ) => {
26+ const [ show1 , setShow1 ] = React . useState ( false ) ;
27+ const [ show2 , setShow2 ] = React . useState ( false ) ;
28+
29+ return (
30+ < React . StrictMode >
31+ < button
32+ onClick = { ( ) => {
33+ setShow1 ( ! show1 ) ;
34+ } }
35+ >
36+ Trigger Inner Child
37+ </ button >
38+ < button
39+ onClick = { ( ) => {
40+ setShow2 ( ! show2 ) ;
41+ } }
42+ >
43+ Trigger Outer Child
44+ </ button >
45+
46+ < Portal open >
47+ < div style = { { border : '1px solid red' } } >
48+ < p > Hello Root { version } </ p >
49+
50+ { show1 && (
51+ < Portal open >
52+ < Child />
53+ </ Portal >
54+ ) }
55+ </ div >
56+ </ Portal >
57+
58+ { show2 && (
59+ < Portal open >
60+ < Child />
61+ </ Portal >
62+ ) }
63+ </ React . StrictMode >
64+ ) ;
65+ } ;
Original file line number Diff line number Diff line change @@ -29,27 +29,35 @@ export default function useDom(
2929 } ) ;
3030
3131 // ========================== Order ==========================
32+ const appendedRef = React . useRef ( false ) ;
33+
3234 const queueCreate = React . useContext ( OrderContext ) ;
3335 const [ queue , setQueue ] = React . useState < VoidFunction [ ] > ( EMPTY_LIST ) ;
3436
3537 const mergedQueueCreate =
3638 queueCreate ||
37- ( ( appendFn : VoidFunction ) => {
38- setQueue ( origin => {
39- const newQueue = [ appendFn , ...origin ] ;
40- return newQueue ;
41- } ) ;
42- } ) ;
39+ ( appendedRef . current
40+ ? undefined
41+ : ( appendFn : VoidFunction ) => {
42+ setQueue ( origin => {
43+ const newQueue = [ appendFn , ...origin ] ;
44+ return newQueue ;
45+ } ) ;
46+ } ) ;
4347
4448 // =========================== DOM ===========================
4549 function append ( ) {
4650 if ( ! ele . parentElement ) {
4751 document . body . appendChild ( ele ) ;
4852 }
53+
54+ appendedRef . current = true ;
4955 }
5056
5157 function cleanup ( ) {
5258 ele . parentElement ?. removeChild ( ele ) ;
59+
60+ appendedRef . current = false ;
5361 }
5462
5563 useLayoutEffect ( ( ) => {
Original file line number Diff line number Diff line change @@ -12,6 +12,12 @@ jest.mock('../src/util', () => {
1212 } ;
1313} ) ;
1414
15+ // Revert `useLayoutEffect` back to real one since we should keep order for test
16+ jest . mock ( 'rc-util/lib/hooks/useLayoutEffect' , ( ) => {
17+ const origin = jest . requireActual ( 'react' ) ;
18+ return origin . useLayoutEffect ;
19+ } ) ;
20+
1521describe ( 'Portal' , ( ) => {
1622 beforeEach ( ( ) => {
1723 global . isOverflow = true ;
@@ -249,4 +255,37 @@ describe('Portal', () => {
249255 rerender ( < Demo open /> ) ;
250256 expect ( checked ) . toBeTruthy ( ) ;
251257 } ) ;
258+
259+ it ( 'not block if parent already created' , ( ) => {
260+ const Checker = ( ) => {
261+ const divRef = React . useRef < HTMLDivElement > ( null ) ;
262+ const [ inDoc , setInDoc ] = React . useState ( false ) ;
263+
264+ React . useEffect ( ( ) => {
265+ setInDoc ( document . contains ( divRef . current ) ) ;
266+ } , [ ] ) ;
267+
268+ return (
269+ < div ref = { divRef } className = "checker" >
270+ { String ( inDoc ) }
271+ </ div >
272+ ) ;
273+ } ;
274+
275+ const Demo = ( { visible } : any ) => (
276+ < Portal open >
277+ { visible && (
278+ < Portal open >
279+ < Checker />
280+ </ Portal >
281+ ) }
282+ </ Portal >
283+ ) ;
284+
285+ const { rerender } = render ( < Demo /> ) ;
286+
287+ rerender ( < Demo visible /> ) ;
288+
289+ expect ( document . querySelector ( '.checker' ) . textContent ) . toEqual ( 'true' ) ;
290+ } ) ;
252291} ) ;
You can’t perform that action at this time.
0 commit comments