web-dev-qa-db-ja.com

React-未定義のプロパティ「setState」を読み取ることができません

何らかの理由で、「React- undefinedのプロパティ 'setState'を読み取れません」というエラーが表示されます。したがって、this.stateは、ユーザーが入力した値で更新されることはありません。コメントアウトされているバインディングを試したところ、ユーザー名の入力を入力できず、nullエラーが発生しないという奇妙な動作が発生しますが、値は未定義です。任意の助けいただければ幸いです。ありがとう。

import __fetch from "isomorphic-fetch";
import React from "react";
import InlineCss from "react-inline-css";
import Transmit from "react-transmit";

import Header from './components/header'

class Registration extends React.Component {

    componentWillMount () {
        if (__SERVER__) {
            console.log("Hello server from Registration");
        }

        if (__CLIENT__) {
            console.log("Hello Registration screen");
        }
    }

    constructor () {
        super()

        this.state = {
            name: '',
            password: ''
        }

         //this.onChangeName = this.onChangeName.bind(this);
         //this.onChangePassword = this.onChangePassword.bind(this);
    }

    onChangeName(e) {
        //this.state.name = e.target.name
        this.setState({ name: e.target.name});
    }

    onChangePassword(e) {
        //this.state.password = e.target.name
        this.setState({ password: e.target.password });
    }


    emptinessChecker(){
        let {name, password} = this.state
        console.log(name)
        if (name === "" || password === "") {
            return true;
        }
        else {
            return false;
        }
    }

    submit() {
        console.log(this)
        console.log(this.state)
        if (this.emptinessChecker()){
            alert("Please do not leave any fields blank!");
        }
        else{
            var xhr = new XMLHttpRequest();   // new HttpRequest instance 
            xhr.open("POST", "/edit");
            xhr.addEventListener("load", e => {
                console.log(xhr.responseText)
            });

            xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
            xhr.send(JSON.stringify(this.state));
            window.location.href= "/success"
        }
    }


    render () {

        //let {username, password} = this.state

        if (__SERVER__) {
            console.log("render server from registration");
        }
        if (__CLIENT__) {
            console.log('we client now!')
        }

        return (
            <InlineCss stylesheet={Registration.css()} namespace="Registration">
                <Header />



                <div>
                    <div className = "Register" >
                        Register
                    </div>


                    <ul className="account-fields">

                        <div className = 'Name'>
                                <label>Username</label>
                                <input type="text" value={this.state.name} onChange={this.onChangeName} />
                        </div>

                        <div className = 'Password'>
                                <label>Password</label>
                                <input type="password" value={this.state.password} onChange={this.onChangePassword} />
                        </div>


                        <div className='submitForm'>
                            <div className='submit' onClick={e=>this.submit()}>Submit</div>
                        </div>

                    </ul>
                </div>

            </InlineCss>




        );
    }
    /**
     * <InlineCss> component allows you to write a CSS stylesheet for your component. Target
     * your component with `&` and its children with `& selectors`. Be specific.
     */
    static css () {
        return (`
            & .Register {
                position: fixed;
                right: 550px;
                bottom: 550px;
                font-size: 50px;
            }
            & .account-fields {
                position: fixed;
                right: 550px;
                bottom: 450px;
                font-size: 20px;
            }
            & .submitForm {
                position: fixed;
                right: 10px;
                bottom: 10px;
                width: 200px;
            }
            & .submit {
                cursor: pointer;
                text-align: center;
                font-size: 20px;
                padding: 10px;
                background-color: #00E4A5;
                color: #fff;
                border-radius: 5px;
                box-shadow: 0 2px 10px 0 rgba(0,0,0,.13);
                border-bottom: 2px solid #00C791;
                text-shadow: 0px -1px 0px #009E73;
            }
        `);
    }

}

export default Transmit.createContainer(Registration);
10
user3708762

これらのイベントハンドラでは、e.target それは <input>イベントをトリガーしました。

onChangeName(e) {
    //this.state.name = e.target.name
    this.setState({ name: e.target.name});
}

onChangePassword(e) {
    //this.state.password = e.target.name
    this.setState({ password: e.target.password });
}

valueプロパティを使用して、入力の値を取得します。

onChangeName(e) {
    this.setState({name: e.target.value});
}

onChangePassword(e) {
    this.setState({password: e.target.value});
}

また、コンストラクタのコメントアウトされたコードに従って、thisが適切にバインドされていることを確認する必要もあります。


入力に適切なnameプロパティを与える場合、これらを単一のonChangeハンドラーに置き換えます。

constructor(props) {
  super(props)
  // ...
  this.onChange = this.onChange.bind(this)
}

onChange(e) {
  this.setState([e.target.name]: e.target.value})
}

render() {
  // ...
  <input type="text" name="name" value={this.state.name} onChange={this.onChange}/>
  <input type="password" name="password" value={this.state.password} onChange={this.onChange}/>
  // ...
}
14
Jonny Buchanan

編集する

コンストラクターでバインディングのパターンに従う場合は、正しいコンストラクター呼び出しを使用していることを確認してください。

constructor (props) {
    super(props)

コンストラクタ内のpropsに注意してください。

元の答え

ES6コンポーネント定義を使用しているように見えるため、レンダリングされたコンポーネント内のthisにバインドする必要があります。

<input type="text" value={this.state.name} onChange={this.onChangeName.bind(this)} />

コンストラクタでこのようなものを定義する必要はありません:

 //this doesn't work
 //this.onChangeName = this.onChangeName.bind(this);
 //this.onChangePassword = this.onChangePassword.bind(this);

また、例のコードを省略している可能性もあるため、例や目的のために不要な部分を削除しようとしているかどうかはわかりませんが、コンポーネントが適切に構造化されていることを確認してください。

5
Josh Beam

アロー関数を使用する場合、バインドする必要はありません。

onNameChange = (e)=> {
this.setState({name:e.target.value});
}

onPasswordChange = (e) => {
this.setState({password:e.target.value});
}
1
Burak Kahraman