mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Fix a crash in Suspense with findDOMNode
This commit is contained in:
committed by
Andrew Clark
parent
6d0effad76
commit
41aa345d2b
@@ -233,4 +233,48 @@ describe('ReactDOMSuspensePlaceholder', () => {
|
||||
await Lazy;
|
||||
expect(log).toEqual(['cDU first', 'cDU second']);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/facebook/react/issues/14188
|
||||
it('can call findDOMNode() in a suspended component commit phase (#2)', () => {
|
||||
let suspendOnce = Promise.resolve();
|
||||
function Suspend() {
|
||||
if (suspendOnce) {
|
||||
let promise = suspendOnce;
|
||||
suspendOnce = null;
|
||||
throw promise;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const log = [];
|
||||
class Child extends React.Component {
|
||||
componentDidMount() {
|
||||
log.push('cDM');
|
||||
ReactDOM.findDOMNode(this);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
log.push('cDU');
|
||||
ReactDOM.findDOMNode(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Suspense fallback="Loading">
|
||||
<Suspend />
|
||||
<Child />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, container);
|
||||
expect(log).toEqual(['cDM']);
|
||||
ReactDOM.render(<App />, container);
|
||||
expect(log).toEqual(['cDM', 'cDU']);
|
||||
});
|
||||
});
|
||||
|
||||
+23
-2
@@ -21,6 +21,8 @@ import {
|
||||
HostRoot,
|
||||
HostPortal,
|
||||
HostText,
|
||||
Fragment,
|
||||
SuspenseComponent,
|
||||
} from 'shared/ReactWorkTags';
|
||||
import {NoEffect, Placement} from 'shared/ReactSideEffectTags';
|
||||
|
||||
@@ -119,8 +121,27 @@ export function findCurrentFiberUsingSlowPath(fiber: Fiber): Fiber | null {
|
||||
let parentA = a.return;
|
||||
let parentB = parentA ? parentA.alternate : null;
|
||||
if (!parentA || !parentB) {
|
||||
// We're at the root.
|
||||
break;
|
||||
// We're either at the root, or we're in a special Fragment
|
||||
// with no alternate, which is how Suspense (un)hiding works.
|
||||
let maybeSuspenseFragment = parentA || parentB;
|
||||
if (maybeSuspenseFragment && maybeSuspenseFragment.tag === Fragment) {
|
||||
const maybeSuspense = maybeSuspenseFragment.return;
|
||||
if (
|
||||
maybeSuspense &&
|
||||
maybeSuspense.tag === SuspenseComponent &&
|
||||
// If state isn't null, it timed out and we have two Fragment children.
|
||||
maybeSuspense.memoizedState !== null
|
||||
) {
|
||||
parentA = maybeSuspense;
|
||||
parentB = maybeSuspense;
|
||||
a = maybeSuspenseFragment;
|
||||
b = maybeSuspenseFragment;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If both copies of the parent fiber point to the same child, we can
|
||||
|
||||
Reference in New Issue
Block a user