2016-12-16 5 views
0

React.CreateClassで記述されたサンプルをReact.Componentに拡張しようとしましたが、イベントハンドラが状態を取得せずに失敗します。誰かが私が間違っていることにいくつかの光を当てることができますか?React.CreateClassをReact.Componentに変換しようとしています

ワーキングサンプル:

var Form4 = React.createClass({ 
    getInitialState: function() { 
     return { 
      username: '', 
      password: '' 
     } 
    }, 
    handleChange: function (key) { 
     return function (e) { 
      var state = {}; 
      state[key] = e.target.value; 
      this.setState(state); 
     }.bind(this); 
    }, 
    resetForm: function() { 
     this.setState({username:'', password: ''}); 
    }, 
    changeFunkyShizzle: function() { 
     this.setState({ 
      username: 'Tom', 
      password: 'Secret' 
     }); 
    }, 
    updateToServer(e) { 
     console.log('update to server....'); 
     console.log(this.state); 
     e.preventDefault(); 
    }, 
    render: function(){ 
     console.log(JSON.stringify(this.state, null, 4)); 
     return (
      <div> 
      <FormFields unamepwd={this.state} handleChange={this.handleChange} updateChanges={this.updateToServer} /> 

     <pre>{JSON.stringify(this.state, null, 4)}</pre> 
     <button onClick={this.changeFunkyShizzle}>Change is near...</button> 
     <button onClick={this.resetForm}>Reset all the things!</button> 
     </div> 
    ); 
} 
}); 

私はそれから作ってみました何:

class Form5 extends React.Component { 
    constructor() { 
     super(); 
     this.state = { 
      username: '', 
      password: '' 
     }; 
    } 
    handleChange(key) { 
     return function (e) { 
      var state = {}; 
      state[key] = e.target.value; 
      this.setState(state); 
     }.bind(this); 
    } 
    changeFunkyShizzle() { 
     this.setState({ 
      username: 'Tom', 
      password: 'Secret' 
     }); 
    } 
    render() { 
     let self = this; 
     console.log(JSON.stringify(this.state, null, 4)); 
     return (
      <div> 
      <FormFields unamepwd={this.state} handleChange={self.handleChange} updateChanges={self.updateToServer} /> 

       <pre>{JSON.stringify(this.state, null, 4)}</pre> 
       <button onClick={this.changeFunkyShizzle}>Change is near...</button> 
       <button onClick={this.resetForm}>Reset all the things!</button> 
       </div>) 
     ; 
    } 
} 

フォームフィールド:

var FormFields = React.createClass({ 
    render: function() { 
     const upwd = this.props.unamepwd; 
     return(
     <form> 
      Username: <input 
     value={upwd.username} 
     onChange={this.props.handleChange('username')} /> 
    <br /> 
      Password: <input type="password" 
     value={upwd.password} 
     onChange={this.props.handleChange('password')} /> 
    <button onClick={this.props.updateChanges}>Go!</button> 
</form> 
     ); 
    } 
}); 

デバッグするとき、私はthis.setState(state);でその両方の場合でthis気づきましたまったく違うものです。 Form5では、Form4では状態を提供しますが、Form4では完全なReactオブジェクトです。

これは、Babelが何か他のものに移していることや、私が拡張しているクラス(React.Component)のためかもしれません。私はReact.jsの世界への第一歩を踏み出しており、すでにかなりのものを稼働させていますが、これは私のためにはうまくいかないし、なぜそうではないのか分かりません。

私はtranspileに使用gulpfile:クラスメソッドで

var gulp = require('gulp'); 
var babel = require('gulp-babel'); 
var sourceMaps = require('gulp-sourcemaps'); 

gulp.task('transpile', function() { 
    gulp.src('source/**.jsx') 
     .pipe(sourceMaps.init()) 
     .pipe(babel({ "presets": "react" })) 
     .pipe(babel({ "presets": "es2015" })) 
     .pipe(sourceMaps.write('.')) 
     .pipe(gulp.dest('app/')); 
}); 

gulp.task('watchers', function() { 
    gulp.watch('source/**.jsx', ['transpile']); 
}); 

gulp.task('default', ['watchers'], function() { 
    console.log('gulp default task running'); 
}); 

答えて

1

は、thisは、自動的に(コンストラクタを除くとライフサイクルメソッドに反応)クラスにバインドされていません。

ソリューション1

バインド機能コンストラクタの内部でこれに:

constructor() { 
    super(); 
    this.state = { 
     username: '', 
     password: '' 
    }; 
    this.handleChange = this.handleChange.bind(this); 
    this.changeFunkyShizzle= this.changeFunkyShizzle.bind(this); 
} 
handleChange(key) { 
    return function (e) { 
     var state = {}; 
     state[key] = e.target.value; 
     this.setState(state); 
    }.bind(this); 
} 
changeFunkyShizzle() { 
    this.setState({ 
     username: 'Tom', 
     password: 'Secret' 
    }); 
} 

ソリューション2

使用矢印機能。これはES6の機能なので、Babelをcorrect pluginに設定する必要があります。

handleChange = (key) => (e) => { 
    var state = {}; 
    state[key] = e.target.value; 
    this.setState(state); 
} 

changeFunkyShizzle =() => { 
    this.setState({ 
     username: 'Tom', 
     password: 'Secret' 
    }); 
} 

ソリューション3

あなたのためにこれを行うには自動バインディングサードパーティのライブラリを使用します。

+0

は、ソリューションが私のためにうまくいくようです。しかし、解決策2は、JSXで許可されていないと受け入れられませんでした。 – XIII

+0

Oups、中括弧を削除するのを忘れました。私の答えを更新しました。また、矢印機能としてBabelが必要な場合は、ES6でのみ使用できます。 – mbernardeau

+0

それを後で試してみます。私はまた属性として、しかしsuccesのないdirectyを渡そうとしました:http://stackoverflow.com/questions/41186015/react-js-passing-in-props。 – XIII

関連する問題