Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

MVP hooks support #1272

Merged
merged 11 commits into from
Jan 14, 2019
Merged

Conversation

bvaughn
Copy link
Contributor

@bvaughn bvaughn commented Jan 9, 2019

Support (read-only) inspectable hooks.

kapture 2019-01-11 at 11 07 44-hooks

Open questions

How should we handle production mode?

How should we handle hooks inspection in production mode? The react-debug-hooks package relies on parsing function names to identify custom hooks. If these names are mangled, they won't be identifiable, and as a result– the hooks tree will look strange.

Development:

screen shot 2019-01-11 at 8 58 00 am

Production:

screen shot 2019-01-11 at 8 58 09 am

…ce "opaque node" just points to whichever fiber happened to be created first for the pair)
@Jessidhia
Copy link

Jessidhia commented Jan 9, 2019

Should the inputs array given to useCallback (2nd argument) also be part of the inspection? It is part of the hook node at least.

@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 9, 2019

No, we aren't currently planning on surfacing that info in DevTools.

@bvaughn bvaughn force-pushed the hooks-integration-experimental branch from 8ce4a2e to b5ac442 Compare January 10, 2019 06:03
@TryingToImprove
Copy link

Given I have component like below:

const C = () => {
   const [person, setPerson] = useState({ name: 'test' });
   const [schools, setSchools] = useState(['test', 'test2]);

   return (<div>{person} went to {schools.join(',')}</div>)

In devtools it will display

- Hooks
   - State: person
   - State: schools

So there will be mutiple "state"-objects in the list if I do not use "custom hooks".

Is what I am describing correct?

@Saifadin
Copy link

@TryingToImprove most likely it will look like this

- Hooks
  - State: {
      name: 'test'
    }
  - State: [
      'test', 'test2'
    ]

@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 10, 2019

I should clarify my previous comment.

Yes, you will see multiple "State" hooks– because you are calling useState multiple times in that example. They'll be listed in the order you've used them in, and they'll show the values currently returned.

So with the code example you provided, it would actually look like this:

Hooks
  State: {…}
  State: Array[2]

@bvaughn bvaughn changed the title Support hooks [WIP] MVP hooks support Jan 11, 2019
@bvaughn bvaughn force-pushed the hooks-integration-experimental branch from 4cc286d to f1a92de Compare January 11, 2019 16:42
@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 11, 2019

Okay, I think this is ready for review.

agent/Agent.js Outdated
}
if (this._prevInspectedHooks !== inspectedHooks) {
this._prevInspectedHooks = inspectedHooks;
this.emit('inspectedHooks', inspectedHooks);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing this (storing data, having Fiber-specific code) in the Agent sucks. I'm open to suggestions for a better place for this logic to live, but at the same time– I didn't stress about it too much because I think this version of DevTools is short lived (without either a rewrite or a refactor).

agent/Agent.js Outdated
if (internals && internals.currentDispatcherRef) {
// HACK: This leaks Fiber-specific logic into the Agent which is not ideal.
// $FlowFixMe
const currentFiber = data.state === internalInstance.memoizedState ? internalInstance : internalInstance.alternate;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is gross for obvious reasons, but it needs to live somewhere. Happy to move it out of the Agent if anyone thinks it's too gross even for a temporary solution.

@gaearon
Copy link
Contributor

gaearon commented Jan 11, 2019

Does it still show "undefined" for Hooks that don't have values? Is that necessary/useful? Can be just empty?

@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 11, 2019

Does it still show "undefined" for Hooks that don't have values? Is that necessary/useful? Can be just empty?

Good call. I added a guard for this.

var containsHooks =
(tag === FunctionComponent ||
tag === SimpleMemoComponent ||
tag == ForwardRef) &&

Choose a reason for hiding this comment

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

Are you wanting to use == for the FowardRef comparison here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Typo. Doesn't actually matter in this case but I'll fix it.

Copy link

@threepointone threepointone left a comment

Choose a reason for hiding this comment

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

I am a merciful god.

(I'll test this later tonight, but lgtm!)

theme: Theme,
};

function HooksNodeView({ hooksNode, index, inspect, path, theme }: HooksNodeViewProps) {

Choose a reason for hiding this comment

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

yo dawg I heard you like hooks

@@ -251,4 +270,9 @@ const noPropsStateStyle = (theme: Theme) => ({
padding: '0.5rem',
});

const hooksTreeLoadingStyle = {

Choose a reason for hiding this comment

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

any reason this isn't in a stylesheet? (low pri, ignore)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just following the (super gross) convention within the file. Old DevTools are pretty gross.

@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 14, 2019

Updated Profiler UI to not show a "State" pane for Fibers using hooks. Unfortunately, we can't show the hooks either– because we can't inspect stale Fibers.

@gaearon
Copy link
Contributor

gaearon commented Jan 14, 2019

Good call. I added a guard for this.

Just to confirm. If I specifically call useDebugValue(undefined) I'd want to see it though. There's a difference between wanting to set undefined as a value, and not having a value.

@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 14, 2019

Just to confirm. If I specifically call useDebugValue(undefined) I'd want to see it though.

There is no way for DevTools to differentiate between the two states of "I explicitly called useDebugValue(undefined)" and "I didn't call useDebugValue" so I chose to optimize for the case I think is far more common.

We can't show hooks values either, unfortunately, since we can't use the ReactDebugHooks util for stale fibers because their props will have changed.
@bvaughn bvaughn force-pushed the hooks-integration-experimental branch from 73ff54c to f456a68 Compare January 14, 2019 18:54
@bvaughn
Copy link
Contributor Author

bvaughn commented Jan 14, 2019

I moved the fiber+hooks specific hacks inside of Agent into a new HooksInspector plugin because they felt pretty dirty, but with that... I think we're good enough for an MVP. Anything else that crops up– I'll fix it in the future! :)

@bvaughn bvaughn merged commit 83ce90d into facebook:master Jan 14, 2019
@bvaughn bvaughn deleted the hooks-integration-experimental branch January 14, 2019 22:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants