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

[WIP] Support hiding components in devtools #1187

Closed
wants to merge 19 commits into from
Closed

[WIP] Support hiding components in devtools #1187

wants to merge 19 commits into from

Conversation

Gvozd
Copy link

@Gvozd Gvozd commented Oct 15, 2018

Add two options for hiding components

  1. For components with [Symbol.for('react.devtools.hide')] = true - rebase of PR Support hiding components in devtools with Symbol.for('react.devtools.hide') #997
  2. If component define displayName - I think that most popular case for HOC

I'm waiting for feedbacks
It is time to move forward on this issue after long discussions.

@facebook-github-bot
Copy link

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need the corporate CLA signed.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@facebook-github-bot
Copy link

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

@Gvozd
Copy link
Author

Gvozd commented Oct 18, 2018

Call in the discussion of interested persons
@gaearon @sebmarkbage @Kovensky @zackargyle @kyleshevlin @jquense @jaredly @shriah @bvaughn

@jaredly
Copy link
Contributor

jaredly commented Oct 19, 2018

Looks good to me! I'm no longer a committer on this project, so I'll have to let someone else merge

@bvaughn
Copy link
Contributor

bvaughn commented Oct 19, 2018

I'm not sure how I feel about the hidden symbol. I don't like the hideDisplayNamed logic on initial read though. It seems unintuitive to me. Maybe you can explain your thought process?

@@ -176,6 +178,8 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer):
publicInstance = fiber.stateNode;
props = fiber.memoizedProps;
state = fiber.memoizedState;
hideSymbol = typeof Symbol === 'function' && fiber.type[Symbol.for('react.devtools.hide')];
hideDisplayNamed = fiber.type.hasOwnProperty('displayName');
Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I'm jet lagged at the moment so maybe this is a stupid question, but why is the "displayName" check here? I don't get how it's related.

@@ -163,7 +163,7 @@ function getBreadcrumbPath(store: Store): BreadcrumbPath {
}

module.exports = decorate({
listeners: () => ['breadcrumbHead', 'selected'],
listeners: () => ['breadcrumbHead', 'selected', 'hideSymbol', 'hideDisplayNamed'],
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is Breadcrumb listening for hideDisplayNamed and hideSymbol when it doesn't use them?

Copy link
Author

Choose a reason for hiding this comment

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

It's used in getBreadcrumbPath > store.skipWrapper

checked={hideDisplayNamed}
onChange={this._changeHideDisplayNamed}
/>
Hide components with custom <code>displayName</code> property
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand why you'd want this particular functionality.

Copy link
Author

Choose a reason for hiding this comment

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

Many HOC's creates wrapper components with custom displayName like SomeWrapper(OriginalComponent)
In contrast, regular components usually do not use dispalyName

I thought that such a simple rule is suitable for a draft, and better than nothing
This is the minimum that I would like to get in order to hide noisy HOC's
I can add/replace with other simple HOC recognition, if they work better.

Choose a reason for hiding this comment

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

Many HOC's creates wrapper components with custom displayName
In contrast, regular components usually do not use dispalyName

There are many that are kind of like "presentation HOC" and assign displayName through babel plugin, i.e styled-components, emotion, jss, etc:

const MyButton = styled.button`
   color: tomato;
`
// MyButton will have displayName: "MyButton" crafted by babel plugin

Although they are technically HOC i'd not want to hide them.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the displayName attribute is too likely to cause false positives, as @asvetliakov points out, due to popular plug-ins like babel-plugin-transform-react-display-name. It also feels too arbitrary to me.

@@ -176,6 +178,8 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer):
publicInstance = fiber.stateNode;
props = fiber.memoizedProps;
state = fiber.memoizedState;
hideSymbol = typeof Symbol === 'function' && fiber.type[Symbol.for('react.devtools.hide')];
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: react-devtools.hide?

@Inve1951
Copy link

I find the method discussed in #676 more appealing.

How about we just dim the components in the tree that have ( or ) in their names? These are always HOCs, as people commonly use X(Y) convention like Connect(App), Relay(FeedItem), or withStyles(Button). You can’t accidentally put parens into the name so it’s always intentional. HOCs that don’t adhere to this convention could easily adapt to it.

For hiding that is, not dimming. Could also have a checkbox in devtools to enable/disable the feature (or maybe even toggle between hiding and dimming).

@bvaughn
Copy link
Contributor

bvaughn commented Oct 19, 2018

I believe I would also be more of a fan of that approach, as it would be more consistent with filtering other categories of components (as described in #1076)

@danielkcz
Copy link

This was so good looking until it wasn't. Would you please remove the second approach with displayName? It's too much opinionated and not that useful. Even though it's opt-in, it would be just confusing.

@Gvozd
Copy link
Author

Gvozd commented Oct 25, 2018

Sorry for the break
Replaced 'Hide components with custom 'displayName' property to Hide HOC's with parens in name
Fixed some bug with breadcrumbs, and selection
Corrected UI
image

In next plans:

  • additional dimming mode
  • optimize performance

@danielkcz
Copy link

@Gvozd thanks, much better.

I am wondering, won't this symbol approach be somewhat problematic in TypeScript or possibly even Flow? Generally attaching foreign properties to objects is rather painful with static typing. Any ideas how it could be solved except using // @ts-ignore above the assignment line?

@Jessidhia
Copy link

I wasn't thinking of attaching it to arbitrary functions but rather to functions/classes you generate yourself as part of the HOC factory function. static [Symbol.for('react-devtools.hide')] = true.

@danielkcz
Copy link

danielkcz commented Oct 26, 2018

Well, for an example I would like to hide all React.createContext so I suppose I would have to do something like this?

const context = React.createContext()
// @ts-ignore
context.Consumer[hideSymbol] = true

This is especially troubling for 3rd party ones. And also some stateless components are useless to be visible in the tree, so that's about attaching a symbol to the existing function.

use-case:
- one of hiding checkbox is enabled
- open full tree of HigherOrderComponent(Nested)
- toggle another checkbox. TreeView is not changed(because HOC hided by another checkbox)

Changed timings for `wrapMultipleNested(Nested, 25/50/100)`
ms: 413/1170/4044 -> 54/94/184
O: O(n^2) -> O(n)
@Gvozd
Copy link
Author

Gvozd commented Oct 27, 2018

  1. I fixed the performance of many nested components
  2. For custom static symbol/ordinary property
    If they are approved by maintainers - need fix ts/flow lib definition for react
    In this case, setting this property should work as well as displayName
    It is also necessary to use an ordinary property, in order to properly support the flow
    Offer hideInDevtools as the name of a static property

@danielkcz
Copy link

I am thinking this is not needed as much anymore by introducing React Hooks. It's obvious that need for HOC and various middle-man components will be gone with this and we will have a naturally clean component tree 🎉

@Gvozd
Copy link
Author

Gvozd commented Oct 28, 2018

TLDR: There are no plans to remove classes from React.

The old HOCs will not disappear anywhere for a long time
Classes do not go anywhere, so the hooks will live for a long time in parallel with the existing APIs, classes, and therefore HOC/render props

It also takes time

  • stabilize RFC
  • while the most popular libraries will add hoke API
    In addition, because hooks do not work with class components, and no one is going to refuse classes
  • when (if) existing projects will be transferred to hooks, and exclusively functional components

This is the case if all developers accept hooks as more convenient, and decide to switch to them in full
Until then (an optimistic assessment for the next year or two), the HOC will be a frequent guest in many already existing projects

So I think that to hide the HOCis still necessary and useful.

@Gvozd
Copy link
Author

Gvozd commented Nov 1, 2018

Upd: support dimming
image

@Gvozd Gvozd changed the title Support hiding components in devtools [WIP] Support hiding components in devtools Nov 12, 2018
@Gvozd
Copy link
Author

Gvozd commented Nov 12, 2018

I think I need to leave only one option of hiding/dimming, for the HOC with parentheses in the name
It is also worth moving these options to SettingsPane, as in #503, only in the form of selectbox, so as not to take up much space
What you think?

@Inve1951
Copy link

I think I need to leave only one option of hiding/dimming, for the HOC with parentheses in the name

I think dimming should be the default. A toggle to hide instead would be usefull.
So basically, off = dimmed, on = hidden.

It is also worth moving these options to SettingsPane, as in #503, only in the form of selectbox, so as not to take up much space

Good idea.

@bvaughn
Copy link
Contributor

bvaughn commented Nov 19, 2018

I don't think the dimming is very useful. It's very subtle and the tree is just as cluttered as before. (I think the primary purpose of hiding components is that the element tree is too crowded.)

I also think it's confusing to have a checkbox that says, e.g. "Hide HOCs..." when they won't actually be hidden unless you select one of three radio options above. I suppose I could imagine a UX where we have a global toggle on/off, but I don't think it's necessary.

I realize this PR has been pretty long running, and I feel bad about the inconvenience. If you'd like, I could pick up where this PR leaves off and make the additions I had planned for #1076 originally?

@Gvozd
Copy link
Author

Gvozd commented Nov 19, 2018

@bvaughn, OK.

@Inve1951
Copy link

I don't think the dimming is very useful. It's very subtle and the tree is just as cluttered as before. (I think the primary purpose of hiding components is that the element tree is too crowded.)

I personally appreciate a dimming option for HOCs, as they are part of the virtual DOM and I'd like to view them as such, but at the same time want them to be visually distinguishable/faded since they are HOCs / less impactful than regular components.

I also think it's confusing to have a checkbox that says, e.g. "Hide HOCs..." when they won't actually be hidden unless you select one of three radio options above. I suppose I could imagine a UX where we have a global toggle on/off, but I don't think it's necessary.

We just talked about this and I agree that the radio buttons are inconvenient. My suggestion was to make a checkbox/toggle for hiding. If dimming gets included in this feature then it could be the off-state of said toggle.

@bvaughn @Gvozd

@Gvozd Gvozd closed this Dec 13, 2018
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