【问题标题】:React: How to use setState in AddListener()?React:如何在 AddListener() 中使用 setState?
【发布时间】:2019-06-16 18:20:50
【问题描述】:

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

TypeError: this.setState 不是函数

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

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

但它仍然返回此错误。我在这里忘记了什么?

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})
    });
}

【问题讨论】:

  • 你能用()=>箭头函数代替function(event)
  • 谢谢! @HaiPham 也建议这样做。
  • @CédricBloem 抱歉缺少解释,我已经更新了我的答案
  • @Hai Pham 没问题!我立即注意到并阅读了文档 :) 感谢您提供的信息!

标签: reactjs listener bind typeerror setstate


【解决方案1】:

在 JavaScript 中,this 总是指我们正在执行的函数的“所有者”,或者更确切地说,指的是函数作为方法的对象。 请改用箭头功能。 箭头函数没有自己的 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 指的是函数的上下文。如果没有上下文,那么this 提供一个全局对象,是的,但是如果你使用函数作为事件监听器,例如,那么this 将引用事件的currentTarget
  • @LevitatorImbalance 感谢您提供的信息,我已经更新了我的答案
【解决方案2】:

普通函数中的this 指的是全局对象或当前实例(如果通过new 调用)。但是箭头函数内部的this 是从外部范围捕获的。所以this里面的addListener回调指的是全局对象(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));
    

【讨论】:

    【解决方案3】:

    首先,我不建议你使用匿名函数来设置事件监听器,因为在这种情况下你将无法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})
    }
    

    希望对您有所帮助! :)

    【讨论】:

    • 它确实有帮助!谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-18
    • 2021-04-20
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多