[英]Reactjs lost touchmove after setState
我有一个关于 Reactjs 的触摸事件的问题。
当触摸移动时,我将调用 setState 来呈现新的 div。
但是如果我继续处理那些新的 div,那么 touchmove 事件就不会再触发了。
就像下面的gif
这是我的示例代码:
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>
);
}
});
现在我只知道如果我将 pointerEvents: none 添加到 div,那么它就可以工作。 有没有人有同样的问题?
将<div key={item}
更改为<div key={index}
。
演示: https : //stackblitz.com/edit/react-5yqumb
你需要改变这部分
{this.state.rows.map(function(item, index) {
return (
<div key={item} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
);
})}
到(看看key={index}
):
{this.state.rows.map(function(item, index) {
return (
<div key={index} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
);
})}
如果你改变了这个
<div key={index} style={{ width: 100, backgroundColor: '#eee' }}>
{item}
</div>
到另一个 React 组件,如:
class Box extends Component {
componentDidMount() {
console.log('mounted <Box />', this.props.children);
}
componentWillUnmount() {
console.log('unmounted <Box />', this.props.children);
}
render() {
return <div style={{ width: 100, backgroundColor: '#eee' }}>{this.props.children}</div>;
}
}
您可以很容易地观察到,在每次状态更新时,您都会挂载和卸载<Box />
组件。 看看这些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
删除和添加 dom 节点是问题的根源。 在您的情况下,您希望在 DOM 中具有相同数量的<div />
并仅更新其内容,因此在该特定上下文中使用索引是安全的。 您可以在官方文档 - Lists and Keys - React 中阅读有关密钥的更多信息。
当您将<div key={item}
更改为<div key={index}
, 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
end
您可以随时尝试在 DOM 中设置断点以查看 DOM 节点是否被删除。
据我所知,这是因为touchmove
和touchend
应该从同一个活动触摸 [1] 分派;
也就是说,一旦你移除了(在这种情况下由于 React 重新渲染)启动touchstart
的元素,它不会进一步调度touchmove
和touchend
事件。
这就是为什么pointer-events: none
似乎使它起作用,因为您只是绕过了可以删除的元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.