I have a question about Reactjs's touch event.
When the touch moves I will call the setState to render new divs.
But if I keep moving on those new divs the touchmove event won't fire anymore.
Just like the gif below
If I moving out of those divs then it's working.
here's my sample code:
var Container = React.createClass({
getInitialState: function () {
return {
index: 0,
rows: this.getRowsByIndex(0)
};
},
getRowsByIndex: function(index) {
var rows = [];
for (var i = index; i < index + 10; i++) {
rows.push(i);
}
return rows;
},
handleTouchStart: function() {
console.log('start')
},
handleTouchMove: function() {
console.log('move')
this.setState({
index: this.state.index + 1,
rows: this.getRowsByIndex(this.state.index + 1)
});
},
handleTouchEnd: function() {
console.log('end')
},
handleTouchCancel: function() {
console.log('cancel')
},
render: function () {
return (
<div style={{ width: 250, height: 300, border: '1px solid' }}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
onTouchCancel={this.handleTouchCancel}>
<div>
{this.state.rows.map(function(item, index) {
return <div key={item} style={{ width: 100, backgroundColor: '#eee' }}>{item}</div>;
})}
</div>
</div>
);
}
});
For now I only know If I added the pointerEvents: none to the div, then it works. Does anyone have the same problem?
I have a question about Reactjs's touch event.
When the touch moves I will call the setState to render new divs.
But if I keep moving on those new divs the touchmove event won't fire anymore.
Just like the gif below
If I moving out of those divs then it's working.
here's my sample code:
var Container = React.createClass({
getInitialState: function () {
return {
index: 0,
rows: this.getRowsByIndex(0)
};
},
getRowsByIndex: function(index) {
var rows = [];
for (var i = index; i < index + 10; i++) {
rows.push(i);
}
return rows;
},
handleTouchStart: function() {
console.log('start')
},
handleTouchMove: function() {
console.log('move')
this.setState({
index: this.state.index + 1,
rows: this.getRowsByIndex(this.state.index + 1)
});
},
handleTouchEnd: function() {
console.log('end')
},
handleTouchCancel: function() {
console.log('cancel')
},
render: function () {
return (
<div style={{ width: 250, height: 300, border: '1px solid' }}
onTouchStart={this.handleTouchStart}
onTouchMove={this.handleTouchMove}
onTouchEnd={this.handleTouchEnd}
onTouchCancel={this.handleTouchCancel}>
<div>
{this.state.rows.map(function(item, index) {
return <div key={item} style={{ width: 100, backgroundColor: '#eee' }}>{item}</div>;
})}
</div>
</div>
);
}
});
For now I only know If I added the pointerEvents: none to the div, then it works. Does anyone have the same problem?
Share Improve this question asked Jun 29, 2018 at 8:31 RayRay 831 silver badge5 bronze badges2 Answers
Reset to default 6tl;dr
Change <div key={item}
to <div key={index}
.
Demo: https://stackblitz./edit/react-5yqumb
A bit longer explanation
You need to change this part
{this.state.rows.map(function(item, index) {
return (
<div key={item} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
);
})}
to (look at key={index}
):
{this.state.rows.map(function(item, index) {
return (
<div key={index} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
);
})}
If you had changed this
<div key={index} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
to another React ponent like:
class Box extends Component {
ponentDidMount() {
console.log('mounted <Box />', this.props.children);
}
ponentWillUnmount() {
console.log('unmounted <Box />', this.props.children);
}
render() {
return <div style={{ width: 100, backgroundColor: '#eee' }}>{this.props.children}</div>;
}
}
You could have observed easily that on every state update, you mount and unmount <Box />
ponents. Look at these console.logs
mounted <Box /> 0
mounted <Box /> 1
mounted <Box /> 2
mounted <Box /> 3
mounted <Box /> 4
mounted <Box /> 5
mounted <Box /> 6
mounted <Box /> 7
mounted <Box /> 8
mounted <Box /> 9
start
unmounted <Box /> 0
mounted <Box /> 10
unmounted <Box /> 1
mounted <Box /> 11
unmounted <Box /> 2
mounted <Box /> 12
unmounted <Box /> 3
mounted <Box /> 13
unmounted <Box /> 4
mounted <Box /> 14
unmounted <Box /> 5
mounted <Box /> 15
unmounted <Box /> 6
mounted <Box /> 16
unmounted <Box /> 7
mounted <Box /> 17
unmounted <Box /> 8
mounted <Box /> 18
Removing and adding dom nodes is the root of the problem. In your case you want to have the same number of <div />
in the DOM and updates just their content so using index in that specific context is safe. You can read more about keys in the official documentation - Lists and Keys - React.
When you change <div key={item}
to <div key={index}
, console.logs
look like this:
mounted <Box /> 0
mounted <Box /> 1
mounted <Box /> 2
mounted <Box /> 3
mounted <Box /> 4
mounted <Box /> 5
mounted <Box /> 6
mounted <Box /> 7
mounted <Box /> 8
mounted <Box /> 9
start
end
You can always try and set breakpoint in the DOM to see that DOM nodes are removed.
with key={index}
with key={item}
As far as I know, that is because the touchmove
and touchend
should be dispatched from the same active touch [1];
That is, once you removed (due to React re-rendering, in this case) the element where touchstart
being initiated, it will not further dispatch touchmove
and touchend
event.
That's why pointer-events: none
seems to make it work, because you just bypassed the element which could be removed.
[1] https://www.w3/TR/touch-events/#event-touchmove
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745509918a4630724.html
评论列表(0条)