Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix findDOMNode incorrectly failing inside Suspense #14198

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -222,4 +222,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']);
});
});
13 changes: 7 additions & 6 deletions packages/react-reconciler/src/ReactFiberTreeReflection.js
Expand Up @@ -117,16 +117,17 @@ export function findCurrentFiberUsingSlowPath(fiber: Fiber): Fiber | null {
let b = alternate;
while (true) {
let parentA = a.return;
let parentB = parentA ? parentA.alternate : null;
if (!parentA || !parentB) {
if (!parentA) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think the logic is designed to make assumptions about which side is which. That’s why it’s a and b instead of say current and workInProgress.

This seems to think that A has some different property than B. Why is this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the logic should have really been !parentA && !parentB. Then we should enter the next if if either is null. But it is impossible for parentA to be null and parentB to be non-null. Hence the asymmetry. I could write it in a more symmetric way but it would have dead branches.

// We're at the root.
break;
}

// If both copies of the parent fiber point to the same child, we can
// assume that the child is current. This happens when we bailout on low
// priority: the bailed out fiber's child reuses the current child.
if (parentA.child === parentB.child) {
// If both copies of the parent fiber point to the same child (or if there
// is only a single parent fiber), we can assume that the child is current.
// This happens when we bailout on low priority: the bailed out fiber's
// child reuses the current child.
let parentB = parentA.alternate;
if (parentB === null || parentA.child === parentB.child) {
let child = parentA.child;
while (child) {
if (child === a) {
Expand Down