Skip to content

Conversation

@gaearon
Copy link
Collaborator

@gaearon gaearon commented Apr 4, 2019

Supersedes #36.

Fixes #60.

This is MVP support for toggling Suspense from the Components pane. We plan a separate tab in #43 but we'd want a way to quickly debug it anyway so seems like this is a good first step.

Showing Suspense Status

Currently, Suspense shows Fiber internal state in the "state" section of the inspector (when Suspended), and nothing if unsuspended. This PR changes so that we show the current Suspense state:

Screen Recording 2019-04-04 at 03 29 PM

This works with older versions of React.

Toggling Suspense Status

The inspected value turns into a checkbox if:

This means that you can toggle Suspense on and off. But if a component actually Suspends by itself, there's nothing to show in the "current" state. In that case the checkbox becomes a read-only label again until it un-Suspends.

Alternatively, we could separate the "current value" from the "override value". But I feel like this is sufficient and intuitive enough in practice after playing with it.

Screen Recording 2019-04-04 at 03 36 PM

Implementation

The simplest implementation would be to always setSuspenseHandler() to the thing that checks IDs in the Set. However, I don't want to incur any Set checking overhead if none of the Suspenses were manually toggled. So I attach and detach the Set-checking handler on demand.

@gaearon gaearon mentioned this pull request Apr 4, 2019
@gaearon gaearon requested a review from bvaughn April 4, 2019 14:39
@gaearon
Copy link
Collaborator Author

gaearon commented Apr 4, 2019

I pushed another commit to fix #60.

Without it, it's kind of a pain to inspect large trees.

Screen Recording 2019-04-04 at 08 14 PM

Copy link
Owner

@bvaughn bvaughn left a comment

Choose a reason for hiding this comment

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

Looks good! Couple of minor nits requested, but otherwise LGTM~

function LoadLater() {
const [loadChild, setLoadChild] = useState(0);
return (
<Suspense
Copy link
Owner

Choose a reason for hiding this comment

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

Selecting this element in the DevTools tree and clicking the load/reload button causes an error:

Uncaught TypeError: Cannot read property 'parentID' of undefined
    at _loop (devtools.js:13578)
    at Bridge.<anonymous> (devtools.js:13649)
    at Bridge.emit (devtools.js:1621)
    at devtools.js:12785
    at devtools.js:21985

Copy link
Owner

Choose a reason for hiding this comment

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

Actually this happens when you toggle via the inspector too (makes sense). Seems like a more important thing to fix.

toggle-bug-Kapture 2019-04-04 at 13 45 36

// Does the current renderer support editable function props?
canEditFunctionProps: typeof overrideProps === 'function',

canEditSuspense:
Copy link
Owner

Choose a reason for hiding this comment

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

naming nit canToggleSuspense ?

setSuspenseHandler,
scheduleUpdate,
} = renderer;
const supportsEditingSuspense =
Copy link
Owner

Choose a reason for hiding this comment

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

naming nit supportsTogglingSuspense ?

function overrideSuspense(id, forceFallback) {
if (
typeof setSuspenseHandler !== 'function' ||
typeof scheduleUpdate !== 'function'
Copy link
Owner

Choose a reason for hiding this comment

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

nit could we just check !supportsEditingSuspense here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Flow wouldn’t be happy

Copy link
Owner

Choose a reason for hiding this comment

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

Oh, right. lol. Ok

mountHelper(ElementTypes);
mountHelper(EditableProps);
mountHelper(DeeplyNestedComponents);
mountHelper(SuspenseTree);
Copy link
Owner

Choose a reason for hiding this comment

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

nit Move this above DeeplyNestedComponents so we can test it without as much scrolling 😆

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I figured maybe you test some other case more often. But fair re: DeeplyNested ones. :-)

}
}
const fiber = idToFiberMap.get(id);
scheduleUpdate(fiber);
Copy link
Owner

Choose a reason for hiding this comment

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

Do we need to call this with the current Fiber or is it robust enough to take either one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Either one would work.

Copy link
Owner

Choose a reason for hiding this comment

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

That makes sense. Just wanted to confirm.

data={state}
overrideValueFn={overrideStateFn}
/>
)}
Copy link
Owner

Choose a reason for hiding this comment

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

I hope we don't end up needing more branching like this 😅

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can refactor if we do. :-) I haven’t seen other cases but they might come up if we add memoizedState to other types.

@bvaughn
Copy link
Owner

bvaughn commented Apr 5, 2019

This looks good to me. Shall we merge it? 😄

@gaearon
Copy link
Collaborator Author

gaearon commented Apr 5, 2019

Still need to fix the suspense fragment behavior. It doesn’t always show the right thing in the tree. Not fault of this PR but I’d like to fix them together.

@gaearon
Copy link
Collaborator Author

gaearon commented Apr 5, 2019

I'll get this in, but I'll keep working on the actual fix for Suspense fragment stuff separately. Because the problem already exists in master anyway.

@gaearon gaearon force-pushed the toggle-suspense-2 branch from f107189 to b8245de Compare April 5, 2019 12:21
@gaearon gaearon merged commit 632647f into bvaughn:master Apr 5, 2019
// Try our best to find the fallback directly.
const maybeFallbackFiber =
(fiber.child && fiber.child.sibling) || fiber;
return renderer.findHostInstanceByFiber(maybeFallbackFiber);

Choose a reason for hiding this comment

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

Should this logic to skip a timed-out Suspense's primary children live in React itself, in findCurrentHostFiber? I don't think it makes a lot of sense for this to live in devtools.

If you findDOMNode from outside a Suspense, you shouldn't get a node back from the primary children. (I think?)

cc @acdlite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants