尝试转换React.CreateClass以扩展React.Component

时间:2016-12-16 12:47:00

标签: javascript reactjs babeljs

我正在尝试转换使用React.CreateClass编写的示例来扩展React.Component但是eventhandler没有获得状态并且对我失败。有人能否解释我做错了什么?

工作样本:

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>)
        ;
    }
}

Formfields:

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>
        );
    }
});

调试时我注意到在thisthis.setState(state);中的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'); }); 完全不同。在Form5中它只提供状态,而在Form4中它是一个完整的React对象,它看起来更多。

这可能是由于Babel将其转换为其他内容或因为我正在扩展的类(React.Component)。我正在迈出React.js世界的第一步并且已经运行了很多东西,但这对我来说并不合适,而且我没有明确指示为什么不这样做。

我用来转换的gulp文件:

@RunWith(AndroidJUnit4.class)
public class Regression extends BaseTest {
    private static final String TAG = TestConstants.TAGPRETEXT + Regression.class.getSimpleName() + " ";

    private ActivityTestRule<MainActivity> activityTestRule;
    private TestName testName;

    @Rule
    public RuleChain chain = RuleChain
            .outerRule(activityTestRule = new ActivityTestRule<>(MainActivity.class))
            .around(testName = new TestName());

    @Override
    public <MainActivity extends AppCompatActivity> MainActivity getActivity() {
        return (MainActivity) activityTestRule.getActivity();
    }

    @Override
    public TestName getTestName() {
        return testName;
    }

    @Test
    public void addBasalProgram24Segments() {
        String programName = "testing" + System.currentTimeMillis() / 1000;

        try {
            new Main()
                    .doBasal()
                    .createBasalSegment(new float[]{1.15f, 14.55f, 0.05f, 12.05f, 19.05f, 21.5f, 20, 1.85f, 10.0f, 1, 2, 4, 15, 26.05f, 10, 30, 15, 4, 25, 15, 5, 12, 10, 20}, programName, new Random().nextInt(5), activityTestRule)
                    .verifyBasalProgramExist(programName);
        } catch (MyEspressoException e) {
            testFailRoutine(e);

        }
    }
}

1 个答案:

答案 0 :(得分:1)

使用类方法时,this不会自动绑定到类(构造函数和React生命周期方法除外)。

解决方案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功能,您可能需要使用correct plugin配置Babel。

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

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

解决方案3

使用自动绑定第三方库为您执行此操作: