React:如何在 AddListener() 中使用 setState?

React: How to use setState in AddListener()?

我有一个方法可以调用 addListener 来处理在您单击按钮之前尚不存在的数据。但是,当我尝试在状态中设置该数据时,出现以下错误:

TypeError: this.setState is not a function

我试过像这样绑定我的 dataHandler:

this.dataHandler = this.dataHandler.bind(this)

但它仍然returns这个错误。我在这里忘记了什么?

constructor(props){
    super(props)
    this.state = {
        selActive: 4,
        loaded: false,
        mapInfo: ''
    }
    this.onScriptLoad = this.onScriptLoad.bind(this)
    this.dataHandler = this.dataHandler.bind(this)
}

dataHandler = (getJson) => {
    fetch(getJson)
        .then(response => response.json())
        .then(featureCollection => 
            dataLayer = map.data.addGeoJson(featureCollection)
        );
    map.data.addListener('mouseover', function(event) {
        map.data.revertStyle();
        map.data.overrideStyle(event.feature, {fillColor: 'blue'});
        // THIS IS WHERE I ADD MY SETSTATE. 
        // HOWEVER, THIS RETURNS AN ERROR ON HOVER
        this.setState({mapInfo: event.feature.countryNL})
    });
}

在 JavaScript 中 this 总是指我们正在执行的函数的 "owner",或者更确切地说,指函数是其方法的对象。 请改用箭头函数。 箭头函数没有自己的 this/super/arguments 绑定。它从其父词法范围继承它们。

map.data.addListener('mouseover', (event) => {
    map.data.revertStyle();
    map.data.overrideStyle(event.feature, {fillColor: 'blue'});
    // THIS IS WHERE I ADD MY SETSTATE. 
    // HOWEVER, THIS RETURNS AN ERROR ON HOVER
    this.setState({mapInfo: event.feature.countryNL})
});

参考:

普通函数中的

this 指的是全局对象或当前实例(在通过 new 调用的情况下)。然而,箭头函数内部的 this 是从外部范围捕获的。因此 thisaddListener 回调中引用全局对象 (window)。要解决此问题,您有以下选择:

  • 使用箭头函数:

    map.data.addListener('mouseover', (event) => {
        map.data.revertStyle();
        map.data.overrideStyle(event.feature, {fillColor: 'blue'});
        // THIS IS WHERE I ADD MY SETSTATE. 
        // HOWEVER, THIS RETURNS AN ERROR ON HOVER
       this.setState({mapInfo: event.feature.countryNL})
    });
    
  • 使用bound function:

    map.data.addListener('mouseover', function (event) {
        map.data.revertStyle();
        map.data.overrideStyle(event.feature, {fillColor: 'blue'});
        // THIS IS WHERE I ADD MY SETSTATE. 
        // HOWEVER, THIS RETURNS AN ERROR ON HOVER
       this.setState({mapInfo: event.feature.countryNL})
    }.bind(this));
    

首先,我不建议你使用匿名函数来设置事件监听器,因为在这种情况下你将无法removeEventListener或类似的东西(可能,因为它不是清楚了,这里的map是什么)。

第二件事是你不应该绑定你的dataHandler,因为它已经是一个箭头函数,所以thisdataHandler上下文中是没有问题的。您应该绑定的是您的手动事件监听器。所以结果代码应该是这样的:

constructor(props){
    super(props)
    this.state = {
        selActive: 4,
        loaded: false,
        mapInfo: ''
    }
    this.onScriptLoad = this.onScriptLoad.bind(this)
    this.dataHandler = this.dataHandler.bind(this)
    this.handleMouseOver = this.handleMouseOver.bind(this)
}

dataHandler = (getJson) => {
    fetch(getJson)
        .then(response => response.json())
        .then(featureCollection => 
            dataLayer = map.data.addGeoJson(featureCollection)
        );
    map.data.addListener('mouseover', this.handleMouseOver);
}

handleMouseOver(event) {
    map.data.revertStyle();
    map.data.overrideStyle(event.feature, {fillColor: 'blue'});
    this.setState({mapInfo: event.feature.countryNL})
}

或者,使用自动绑定的箭头函数:

constructor(props){
    super(props)
    this.state = {
        selActive: 4,
        loaded: false,
        mapInfo: ''
    }
    this.onScriptLoad = this.onScriptLoad.bind(this)
    this.dataHandler = this.dataHandler.bind(this)
}

dataHandler = (getJson) => {
    fetch(getJson)
        .then(response => response.json())
        .then(featureCollection => 
            dataLayer = map.data.addGeoJson(featureCollection)
        );
    map.data.addListener('mouseover', this.handleMouseOver);
}

handleMouseOver = (event) => {
    map.data.revertStyle();
    map.data.overrideStyle(event.feature, {fillColor: 'blue'});
    this.setState({mapInfo: event.feature.countryNL})
}

希望对您有所帮助! :)