2016-12-16 3 views
0

Я пытаюсь преобразовать образец, написанный с React.CreateClass, для продолжения React.Component, но обработчик событий не получает состояние и не работает на меня. Может кто-то пролить свет на то, что я делаю неправильно?Пытается преобразовать React.CreateClass в extends 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 в this.setState(state); это нечто совершенно иное. В Form5 он предоставляет только состояние, в то время как в Form4 это полный объект React, он, похоже, больше на нем.

Возможно, это связано с тем, что Бабель переводит его в нечто другое или из-за класса, в котором я расширяюсь (React.Component). Я делаю первые шаги в мире React.js и уже получил некоторые вещи, но это не работает для меня, и у меня нет четкого указания, почему бы и нет.

gulpfile Я использую transpile:

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 автоматически не связан с классом (за исключением конструктора и React методов lifecyle).

Решение 1

Bind функции к этому внутри конструктора:

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

Я попробую это позже. Я также пробовал его передавать директиву как атрибут, но без прецедентов: http://stackoverflow.com/questions/41186015/react-js-passing-in-props. – XIII