在嵌套的addEventListener函数内使用setState时,“ this.setState不是函数”

时间:2019-02-10 01:27:03

标签: javascript reactjs setstate

我一生无法通过我的react组件传递此TypeError。我已经阅读了每个相关的线程,并实施了几乎所有建议的修复方法,但没有成功。

import React, { Component } from "react";

class Wave extends Component {
    state = {
        position: 44
    };

    changePosition = () => {
        let parentDiv = document.getElementById('parentDiv');
        //this.setState({position: 3})

        parentDiv.addEventListener('click', function (e) {
            let offset = this.getClientRects()[0];          
            alert(e.clientX - offset.left);
            let xcord = e.clientX - offset.left;
            this.setState({position: xcord})
        }, false);
    }

    render() {          
        return (
            <div id={"parentDiv"}>
                <div id={"childDiv"} onClick={this.changePosition}>HI THERE!</div>
            </div>
        );
    }
}

export default Wave;

我了解到我正在失去React类this的上下文,并尝试将changePosition方法绑定到组件构造函数中似乎无效的方法。我还尝试在addEventListener函数末尾使用.bind(this)-

changePosition = () => {
    let parentDiv = document.getElementById('parentDiv');
    //this.setState({position: 3})

    parentDiv.addEventListener('click', function (e) {
        let offset = this.getClientRects()[0];          
        alert(e.clientX - offset.left);
        let xcord = e.clientX - offset.left;
        this.setState({position: xcord})
    }.bind(this), false);
}

但是,当我执行此操作以及尝试将addEventListener函数更改为箭头函数(e) => {时,我就剩下TypeError: this.getClientRects is not a function

对于如何解决此错误的任何启发,都非常感激,因为这已经消耗了我一天的最后2-3个小时。非常感谢你!

1 个答案:

答案 0 :(得分:1)

parentDiv.addEventListener('click', function (e) {
    let offset = this.getClientRects()[0];  // this refers to parentDiv        
}

将此更改为箭头功能以正确绑定this

parentDiv.addEventListener('click', (e) => {
    let offset = parentDiv.getClientRects()[0];  // this refers to Wave component, so we use the actual div reference
    alert(e.clientX - offset.left);
    let xcord = e.clientX - offset.left;
    this.setState({position: xcord}); // works fine
}, false);