React死循环问题

版权声明:本文为博主逝水流光原创,可以转载,请注明出处。 https://blog.csdn.net/javao_0/article/details/79206560
问题提出:

今天在使用React的时候发生了死循环情况,现在拿出来跟大家讨论讨论,其中大致代码如下:

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

const Button = ({ onClick, children }) => {
    return (
        <button type="button"
            onClick={event => {
                if (!!onClick) {
                    onClick(event);
                }
            }}>{children}</button>
    );
}

function handleClick() {
    this.setState({count:++this.state.count});
    console.log("click done!");
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state={count :0,color:"red"}
    }

    componentDidMount() {
    }
    render() {
        return (
            <div>
                <Button onClick={handleClick.call(this)}>点我</Button>
                {this.state.count}
            </div>
        )
    }
}

export default App;
ReactDOM.render(<App />, document.querySelector("#app"));

运行后浏览器会报这样的错误:

Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

在低版本的React可能不会出现上面这样的错误,而直接进入死循环中,直到内存消耗殆尽。

问题分析:

代码的效果很简单就是点击一下按钮,数字加一下。这里把按钮封装了一下。请看render方法里面的onClick方法,这里调用handleClick.call(this)而这个并不是一个函数,而是函数的执行,所以到这一行React会执行这个函数,但是函数里面又调用了setState方法,这个方法改变状态后又会重新渲染DOM,也就会再次调用render方法。同样的,该方法执行的时候又会调用handleClick.call(this),再次循环上面的逻辑,因此陷入了死循环之中。

解决问题:

这里handleClick.call(this)有问题,我们调用这的目的是为了绑定this,而不需要执行,所以这行代码改成handleClick.bind(this)即可。当然还有另外一种解决办法,就是在方法中调用函数,代码如下:

<Button onClick={()=>{
    handleClick.call(this)
    }}>点我</Button>
扩展延伸:

这里出现错误的原因是有call方法调用所导致的,那么我们很有必要了解一下callapplybind三个方法的区别,这三者都是用来改变this的指向的,但是也有不一样的地方,具体区别如下:

1.callapply的效果是一样的都是绑定this,并且调用。只是语法有所区别。call绑定this的语法是这样的func.call(this, arg1, arg2),apply绑定this的语法是这样的func.apply(this, [arg1, arg2])。也就是说除了第一个参数是绑定对象外,call的参数和原本的函数调用顺序是一致的,但是apply的第二个参数是原先参数的一个数组形式。
2.bind是ES5(几乎现在所有的主流浏览器都支持)增加语法,它只是绑定this,但不会立即调用。

猜你喜欢

转载自blog.csdn.net/javao_0/article/details/79206560