无法获取未定义或空引用的属性“setState”

时间:2017-04-20 14:53:20

标签: reactjs babel

我正在尝试为应用添加一些过滤但我的更改处理程序似乎没有引用'this'?知道我在这里做错了吗?

class ShipmentList extends Component {
    constructor(props) {
        super(props)
        this.state = {
            shipments: [],
            searchString: '',
            loading: false
        }
    }

    handleChange(e){
    this.setState( {searchString:e.target.value} )   // <- This is where the error happens  
    }

    componentDidMount() {
        this.setState({loading: true})
        fetch('/shipments-server.json')
        .then(response => response.json())
        .then(shipments => this.setState({
            shipments,
            loading: false
        }))

    render() {
    const { shipments, loading, searchString } = this.state
    var shipmentData = shipments
    var filter = this.state.searchString

    if( filter.length > 0 ) {
        shipmentData = shipmentData.filter(s => {
            return s.carrierName.toLowerCase().match( filter.trim().toLowerCase() )
        });
    }


    return (
        <div className="shipment-list">
            <ul className="filters">
                <li><input value={this.state.searchString} onChange={this.handleChange} placeholder="Filter by Carrier" type="text" /></li>

我的数据从JSON文件加载得很好,但是当我输入到输入文本框并且调用了handleChange()方法时,我看到错误'无法获取属性'setState'为undefined或null reference'。当我在编译代码中设置断点时,我可以看到在handleChange()方法的范围内未定义'this',但我不明白为什么。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

使用较新的ES6类语法时,您将失去createClass提供的自动绑定功能。这是一个刻意的改变,因为JavaScript类也没有进行自动绑定(所以行为是一致的),你可以在这里阅读更多相关内容:https://facebook.github.io/react/docs/react-without-es6.html#autobinding

要解决此问题,您可以返回旧的createClass语法,也可以通过以下两种方式手动将上下文绑定到您的方法:

  1. 对方法使用bind()<input onChange={this.handleChange.bind(this)} />
  2. 包含箭头功能:<input onChange={() => this.handleChange()} />
  3. 使用ES7绑定操作符(需要正确的Babel配置):<input onChange={::this.handleChange} />
  4. 这个的一个小问题是bind()和箭头函数声明(可能也是绑定运算符,但不是100%肯定)基本上会创建一个新方法,每次render()函数被调用。这有一些性能影响(尽管您通常不必担心这一点)。但是,如果这是一个问题,您可以考虑在初始化时将有界方法分配给变量并参考该变量。像这样:

    constructor(props) {
      // ...
      this.handleChange = this.handleChange.bind(this);
    }
    

    或者,如果您的Babel配置允许使用Class Properties语法,您甚至可以跳过必须编写类似这些的分配(并且必须在需要时找出它们),只需直接使用箭头函数即可:

    class ShipmentList extends Component {
    
        handleChange = () => {
            // your handleChange code
        }
    }
    

答案 1 :(得分:2)

您需要绑定this。在构造函数中尝试这个:

constructor(props) {
    super(props)
    this.state = {
        shipments: [],
        searchString: '',
        loading: false
    }
    this.handleChange = this.handleChange.bind(this);
}

答案 2 :(得分:2)

你缺少绑定handleChange试试这样:

<input value={this.state.searchString} onChange={this.handleChange.bind(this)} placeholder="Filter by Carrier" type="text" />

编辑1

就像@fabian-schultz指出的那样,如果你担心性能的下降,你也可以在构造函数中做到这一点:

 constructor(props) {
        super(props)
        this.state = {
            shipments: [],
            searchString: '',
            loading: false
        }
       this.handleChange = this.handleChange.bind(this);
    }