使用触摸手势时渲染调用每个setState

时间:2017-11-20 14:41:10

标签: reactjs hammer.js

我在react.js应用中使用触控手势时遇到问题。问题是每个setState调用都会调用render()函数,而不仅仅是在最后。只有在使用Hammer.js处理点击时才会发生这种情况。如果使用常规按钮,则只调用一次render()函数。

有几点需要注意:

  • 我也尝试使用react-hammerjsZingTouch得到完全相同的结果。
  • 在示例中,我只使用点按“手势”,但如果使用滑动手势,则结果相同。
  • 我尝试将MobX用于状态。但同样的结果也是如此。

以下是我尝试尽可能简单的示例(该示例没有意义,但说明了问题):

import React from 'react';
import ReactDOM from 'react-dom';
import Hammer from 'hammerjs';

class Game extends React.Component {
    constructor(props) {
        super(props);
        this.state = { value: 1 };
    }

    action() {
        console.log(1)
        this.setState({ value: 1 });
        console.log(2)
        this.setState({ value: 2 });
        console.log(3)
        this.setState({ value: 3 });
        console.log(4)
        this.setState({ value: 4 });
        console.log(5)
    }

    componentDidMount() {
        this.hammer = Hammer(this._touchdiv);
        this.hammer.on('tap', () => this.action());
    }

    componentWillUnmount() {
        this.hammer.off('tap', this.action)
    }

    render() {
        console.log('Render');

        return (
            <div>
                {this.state.value}
                <div ref={(el) => this._touchdiv = el}> Touch div</div>
                <button onClick={() => this.action()} value='update' >Normal button</button>
            </div>
        );
    }
}

ReactDOM.render(<Game />, document.getElementById('root'));

使用常规按钮时的控制台输出:

1
2
3
4
5
Render

使用“touch div”时的控制台输出:

1
Render
2
Render
3
Render
4
Render
5

我试图谷歌但却找不到任何类似的例子。

知道发生了什么事吗?欢迎任何可能的解决方案。

编辑1:

ReyHaynes建议裁判可能是问题所在。我试图改变

<div ref={(el) => this._touchdiv = el}> Touch div</div>

<div className='xxx'> Touch div</div>

并更改了

this.hammer = Hammer(this._touchdiv);

this.hammer = Hammer(document.getElementsByClassName("xxx")[0]);

结果完全一样。是的,这是脏代码,但它说明问题存在而不使用ref。

2 个答案:

答案 0 :(得分:0)

使用引用时,一旦状态发生更改,您将重新呈现UI中依赖于该状态的所有组件。

React将确保只更新DOM的正确位,使整个事情变得高效,但调用render来检查必要的更改。

以下是关于该文档的文档:https://reactjs.org/docs/refs-and-the-dom.html

基本上,触摸代码的这一部分导致let calendarUtil = CalendarUtility(title: event.title, location: event.location, notes: event.notes, managedObjectContext: managedObjectContext) 运行:

render()

答案 1 :(得分:0)

检查调用堆栈似乎与触发回调的方式不同。

如果手势被识别,Hammer只会调用回调。

React捕获click事件并将标志'isBatchingUpdates'设置为true,从而使渲染要等到所有setState完成。

编辑: 发现这篇文章解释为:https://itnext.io/react-setstate-usage-and-gotchas-ac10b4e03d60

“当前(第16和更早的版本),默认情况下,仅批处理React事件处理程序中的更新。”