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

[ClickAwayListener] Refactor click-away detection #20992

Closed
wants to merge 3 commits into from

Conversation

eps1lon
Copy link
Member

@eps1lon eps1lon commented May 11, 2020

Initial plan was adding a test for #20409

I originally thought we should rather check node.isConnected instead of looping through the composed path and realized that documentElement.contains isn't a meaningful check since it can only be false if:

  1. event.target is not in the same frame as nodeRef.current
  2. event.target is not connected?

Point 1 is impossible since the event handler is attached to the ownerDocument of nodeRef.current.

Point 2 is only an assumption from #20409. I need to check if the new test was failing prior to #20409 and obviously verify the new build on the sandbox in #20197

Edit:

@eps1lon eps1lon added new feature New feature or request component: ClickAwayListener The React component labels May 11, 2020
@oliviertassinari
Copy link
Member

oliviertassinari commented May 11, 2020

@eps1lon I see what you are doing here, you want to incentive me to provide a failing test case 😄. You are right, the linked pull request misses a test case, if not two. My bad for merging it too quickly. Here is it:

diff --git a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
index 96585ad50..cf360e9b1 100644
--- a/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
+++ b/packages/material-ui/src/ClickAwayListener/ClickAwayListener.test.js
@@ -5,7 +5,7 @@ import { createClientRender, fireEvent, screen } from 'test/utils/createClientRe
 import Portal from '../Portal';
 import ClickAwayListener from './ClickAwayListener';

   const render = createClientRender();

   it('should render the children', () => {
@@ -259,5 +259,23 @@ describe('<ClickAwayListener />', () => {

       expect(handleClickAway.callCount).to.equal(0);
     });
+
+    it(`${eventName} does not trigger onClickAway if an inside target is removed and disableReactTree`, () => {
+      const handleClickAway = spy();
+      function Test() {
+        const [buttonShown, hideButton] = React.useReducer(() => false, true);
+
+        return (
+          <ClickAwayListener onClickAway={handleClickAway} disableReactTree>
+            <div>{buttonShown && <button {...{ [eventName]: hideButton }} type="button" />}</div>
+          </ClickAwayListener>
+        );
+      }
+      render(<Test />);
+
+      screen.getByRole('button').click();
+
+      expect(handleClickAway.callCount).to.equal(0);
+    });
   });
 });

I hope it helps. It was meant to better support disableReactTree.

@eps1lon
Copy link
Member Author

eps1lon commented May 11, 2020

You are right, the linked pull request misses a test case, if not two. My bad for merging it too quickly. Here is it:

I already added tests for the linked PR. Your test is a new one since disabelReactTree wasn't available when #20197 was reported.

@eps1lon
Copy link
Member Author

eps1lon commented May 11, 2020

Could somebody please add documentation for disableReactTree? The name is not descriptive and the documentation simply copied from another prop.

@oliviertassinari
Copy link
Member

What do you think about this description for the prop?

  /**
   * If `true`, the React tree is ignored, only the DOM tree is considered
   * for detecting click outside of the child.
   * This prop changes how portaled elements are handled.
   */
  disableReactTree: PropTypes.bool,

@eps1lon
Copy link
Member Author

eps1lon commented May 11, 2020

Why was this even introduced? It was introduced in a PR that linked an issue in which we decided to not do it:

We should delay the introduction of the disableReactTree prop, it would be great to wait for the outcome of facebook/react#11387 to settle on this prop. We are working on the edges of React, it's better to maximize for future flexibility. We want to reduce the chance of introducing a breaking change in the future.

We could've had a nice transition to React Scope API but now we have a feature that cannot work with it. What a mess.

@eps1lon eps1lon closed this May 11, 2020
@eps1lon eps1lon deleted the feat/ClickAway/refactor branch May 11, 2020 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: ClickAwayListener The React component new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants