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

touchmove doesn't fire on removed element #1355

Open
sophiebits opened this issue Apr 4, 2014 · 13 comments
Open

touchmove doesn't fire on removed element #1355

sophiebits opened this issue Apr 4, 2014 · 13 comments

Comments

@sophiebits
Copy link
Contributor

If you have

{this.state.show &&
  <div onTouchStart={this.hideTheDiv} onTouchMove={...} />}

such that the onTouchStart handler removes the div (and maybe replaces it with another one in the same place, useful in certain draggable interactions), the onTouchMove handler doesn't fire because the events of a detached element no longer bubble to document. We should probably bind the touchmove handler when the element receives touchstart instead of delegating to document.

Sort of related to #1254.

cc @Merbs @eater

@jordwalke
Copy link
Contributor

Is this in the DOM spec? It's kind of strange.

@sophiebits
Copy link
Contributor Author

Sorry, what's strange? Unlike mousemove, touchmove always fires on the element that received touchstart. In my limited testing, browsers happily send events to that removed element.

@sophiebits
Copy link
Contributor Author

You can test http://jsbin.com/gocuhifa/1 on device or in Chrome/Firefox with touch events enabled (touch down on "monkey"; it'll disappear; move your finger and you'll get an alert).

@sophiebits
Copy link
Contributor Author

Hmmmm maybe this isn't supposed to work:

https://docs.google.com/document/d/12-HPlSIF7-ISY8TQHtuQ3IqDi-isZVI0Yzv5zwl90VU/edit#heading=h.q2zqz8v0mja7

I sort of feel like it should still work in React just as well as it does in the browser though.

@sophiebits
Copy link
Contributor Author

See also the W3C public-webevents list where I asked about this behavior.

@sophiebits
Copy link
Contributor Author

This question is likely related: http://stackoverflow.com/q/24537000/49485.

@sophiebits
Copy link
Contributor Author

@m-toyoda
Copy link

m-toyoda commented Jan 5, 2015

+1

@davidspiess
Copy link

Same problem :/

@92hackers
Copy link

Optional solution:
just hide the to removed element, such as css: position: absolute; z-index: -100;

@nikitaeverywhere
Copy link

nikitaeverywhere commented Aug 18, 2020

touchmove and touchend events should always stick to the touchstart target. Check this answer for the correct implementation.

I believe in react this can be implemented manually with the user of ref now. However, as for React's onTouchStart/onTouchMove/onTouchEnd, I would expect them all to be bound to the onTouchStart target.

@Nazeeh21
Copy link

I have been reading all the comments on this issue. So far, I understood that onTouchMove/onTouchEnd events should be bind to the onTouchStart event. If I got it correctly I would like to give it a try to fix this issue.

@Skand17
Copy link

Skand17 commented Jan 23, 2023

You are correct that when the div is removed from the DOM, its events will no longer bubble to the document and the onTouchMove handler will not fire. One solution to this problem is to bind the onTouchMove handler when the div receives a touchstart event, rather than delegating to the document.

Here is an example of how you might do this:

class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { show: true };
this.hideTheDiv = this.hideTheDiv.bind(this);
this.onTouchStart = this.onTouchStart.bind(this);
this.onTouchMove = this.onTouchMove.bind(this);
}
hideTheDiv() {
this.setState({ show: false });
}
onTouchStart(e) {
e.currentTarget.addEventListener("touchmove", this.onTouchMove);
}
onTouchMove(e) {
// handle touchmove event here
}
render() {
return (
this.state.show && (


)
);
}
}

In this example, when the div receives a touchstart event, the onTouchStart handler is called and it attaches the onTouchMove handler to the div element, so that it will fire when the user moves their finger. Additionally, it is important to remove the 'touchmove' event listener when the div is detached, to avoid memory leaks. This can be done by adding an onTouchEnd event that removes the 'touchmove' event listener.

It's worth noting that this approach may not be ideal if you need to handle touchmove events on multiple elements, because you will have to attach and remove event listeners on each element individually. In this case, it might be more appropriate to use a library such as Hammer.js that is specifically designed for handling touch and gesture events in a more efficient and flexible way.

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

No branches or pull requests