未捕获的TypeError:无法读取未定义的属性“状态或道具”

reactjs React.js

猴子村村

2020-05-28

因此,我开始将应用程序从ES2015转换为使用React的ES6。

我有一个家长班和一个孩子班,

export default class Parent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            code: ''
        };
    }

    setCodeChange(newCode) {
        this.setState({code: newCode});
    }


    login() {
        if (this.state.code == "") {
            // Some functionality
        }
    }

    render() {
        return (
            <div>
                <Child onCodeChange={this.setCodeChange} onLogin={this.login} />
            </div>
        );
    }
}

儿童班

export default class Child extends Component {
    constructor(props) {
        super(props);
    }

    handleCodeChange(e) {
        this.props.onCodeChange(e.target.value);
    }

    login() {
        this.props.onLogin();
    }

    render() {
        return (
            <div>
                <input name="code" onChange={this.handleCodeChange.bind(this)}/>
            </div>
            <button id="login" onClick={this.login.bind(this)}>
        );
    }
}

Child.propTypes = {
    onCodeChange: React.PropTypes.func,
    onLogin: React.PropTypes.func
};

但是,这会导致以下错误,

this.state是未定义的

它指的是,

if (this.state.code == "") {
    // Some functionality
}

知道是什么原因造成的吗?

第4191篇《未捕获的TypeError:无法读取未定义的属性“状态或道具”》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

2个回答
神奇神奇Near 2020.05.28

您可以使用箭头功能来绑定您的功能。您需要在子组件和父组件中都绑定功能。

上级:

export default class Parent extends Component {
    constructor(props) {
        super(props);
        this.state = {
            code: ''
        };
    }

    setCodeChange = (newCode) => {
        this.setState({code: newCode});
    }


    login = () => {
        if (this.state.code == "") {
            // Some functionality
        }
    }

    render() {
        return (
            <div>
                <Child onCodeChange={this.setCodeChange} onLogin={this.login} />
            </div>
        );
    }
}

儿童

export default class Child extends Component {
    constructor(props) {
        super(props);
    }

    handleCodeChange = (e) => {
        this.props.onCodeChange(e.target.value);
    }

    login = () => {
        this.props.onLogin();
    }

    render() {
        return (
            <div>
                <input name="code" onChange={this.handleCodeChange}/>
            </div>
            <button id="login" onClick={this.login}>
        );
    }
}

Child.propTypes = {
    onCodeChange: React.PropTypes.func,
    onLogin: React.PropTypes.func
};

There are other ways to bind the functions as well such as the one you are using but you need to do that for parent component too as <Child onCodeChange={this.setCodeChange.bind(this)} onLogin={this.login.bind(this)} />

or you can specify binding in the constructor as

Parent:

constructor(props) {
    super(props);
    this.state = {
        code: ''
    };
 this.setCodeChange = this.setCodeChange.bind(this);
 this.login = this.login.bind(this);
}

Child

constructor(props) {
    super(props);
    this.handleCodeChange = this.handleCodeChange.bind(this);
    this.login = this.login.bind(this);
}
番长樱梅 2020.05.28

我同意@Shubham Kathri提供的所有不同解决方案,除了在render中直接绑定。

不建议您直接在render中绑定功能。建议始终将其绑定到构造函数中,因为如果直接在render中绑定,则每当组件渲染时,Webpack都会在捆绑文件中创建一个新的函数/对象,因此Webpack捆绑文件的大小会增加。由于许多原因,您的组件会重新渲染,例如:执行setState,但是如果将其放置在构造函数中,则只会调用一次。

不建议以下实现

<Child onCodeChange={this.setCodeChange.bind(this)} onLogin={this.login.bind(this)} />

始终在构造函数中执行此操作,并在需要时使用ref

constructor(props){
  super(props);
  this.login = this.login.bind(this);
  this.setCodeChange = this.setCodeChange.bind(this);
}

<Child onCodeChange={this.setCodeChange} onLogin={this.login} />

如果您使用的是ES6,则不需要手动绑定,但是如果需要的话。如果您想避免与范围相关的问题和手动功能/对象绑定,可以使用箭头功能。

抱歉,我的手机上有错别字

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android