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

When Draggable unmounts, if a textbox is focused, the textbox loses focus inexplicably #315

Closed
lukeknep opened this issue Feb 19, 2018 · 10 comments

Comments

@lukeknep
Copy link

lukeknep commented Feb 19, 2018

My app renders some Items depending on the content of several text input.

The Items each contain a Draggable.

I'm coming across this very strange behavior:

  • I type a valid value into a textbox, causing some Items to render
  • Without leaving the textbox, I delete or add a few characters to make the value invalid
  • The Items disappear (unmount)
  • My textbox suddenly loses focus. However, no onBlur handlers are called, and if I switch tabs / windows and then switch back, focus is restored
  • I can prevent this issue by deleting the Draggable component

Here's a codesandbox showing the issue:
https://codesandbox.io/s/32x3voojm5

I can consistently reproduce this.

Browser is Chrome 64.0.3282.119 (Official Build) (64-bit) on Mac OSX.

@lukeknep
Copy link
Author

Temporary workaround is to only render the Draggable when the component I care about is hovered, or only when the textbox is not focused. But both of those have flaws.

BTW this happens so consistently in our application that, without this workaround, we would not be able to use React Draggable in our application.

@skvale
Copy link

skvale commented Feb 26, 2018

Looks like it is an issue in the enableUserSelectHack prop

enableUserSelectHack causes this to be called

export function removeUserSelectStyles(doc: ?Document) {
  try {
    if (doc && doc.body) removeClassName(doc.body, 'react-draggable-transparent-selection');
    window.getSelection().removeAllRanges();  // remove selection caused by scroll
  } catch (e) {
    // probably IE
  }
}

You could try

<Draggable enableUserSelectHack={false}>

But I didn't look into what consequence not calling removeUserSelectStyles would have.

Working: https://codesandbox.io/s/944j9x101o

@STRML
Copy link
Collaborator

STRML commented Feb 26, 2018

Hmm. The user-select hack is necessary to ensure we don't start dragging text all over the page when using the draggable, but calling it on componentWillUnmount is a bit of a hack that ensures that we clean up after ourselves. It may be safe to completely remove it, or at the very least check if a drag is still in progress and only then clean up. But I believe handleDragStop() should be called in all circumstances.

@RomaricMourgues
Copy link

RomaricMourgues commented Mar 15, 2018

I resolved it by adding :

enableUserSelectHack={false}
onStart={(event) => {$("body").addClass("dragging");}}
onStop={(event) => {$("body").removeClass("dragging");}}

on and

body.dragging {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

in style.css.

Thanks for your comment about enableUserSelectHack, it helped !

@lc-stevenzhang
Copy link

Thank you guys!
I have encounter the same problem, my filter lose focus cause the Draggable.
And
enableUserSelectHack={false}
fixed my problem.

@paul-pro
Copy link

paul-pro commented Feb 1, 2019

Not directly related to the focus issue, but I have had a rare selection bug:
if there is ::selection normalization in css (added with some antd lib code in my case) and there is both color and background were set, text becomes white on dragging handler. See repro (+ possible solution): https://codesandbox.io/s/n54p5mwm60

Should we somehow improve current addUserSelectStyles implementation? If @mzabriskie or @STRML approves I can create PR with all: inherit style in this function.

@STRML
Copy link
Collaborator

STRML commented Aug 16, 2019

Fixed in v3.3.2.

@STRML STRML closed this as completed Aug 16, 2019
@ghost
Copy link

ghost commented Oct 24, 2019

@STRML Is it possible that this problem still exists in v.4.0.3? Use case: I have a list of draggable items and I want to search in this list. When the list rerenders, the search field loses focus.
👉 https://stackblitz.com/edit/react-draggable-search

mperrotti added a commit to d2iq/ui-kit that referenced this issue Oct 28, 2019
When react-draggable's Draggable component unmounts, it causes text inputs to lose focus. These changes add a workaround for this problem: react-grid-layout/react-draggable#315
@MattMorrisDev
Copy link

I'm also still having related issues using the latest release.

Adding enableUserSelectHack={false} fixes the textbox losing focus issue for me, but that prevents my dragging from actually showing any movement until the drag finishes (and then it just snaps all the way to the end).

@schnerd
Copy link
Contributor

schnerd commented Jan 8, 2020

Yeah, I'm not sure how the change in 3.3.2 is supposed to fix this issue. The de-focusing is caused by the window.getSelection().removeAllRanges() call.

Modifying react-draggable to check selection.type would fix it:

const selection = window.getSelection();
if (selection && selection.type !== 'Caret') {
  selection.removeAllRanges();
}

Tested this change locally with yarn link and it works fine. Opened PR #450 in case you'd like to merge.

I also wonder why *::selection {all: inherit;} is used instead of user-select: none; (After testing it seems like this has the nice side effect of causing overflowing containers/viewports to scroll as you drag near the edges)

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

No branches or pull requests

8 participants