我试图在React类中绑定异步函数。以前我一直这样使用co
import React from 'react';
import { bind } from 'lodash';
import { wrap } from 'co';
import ajax from 'qajax';
export default class Foo extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = bind(wrap(this.handleSubmit), this);
}
*handleSubmit(event) {
event.preventDefault();
const Data = { foo: this.state.foo };
const Result = yield ajax({ /* ... */ data: Data })
//...
}
}
工作正常。
我试图重构它以使用babel提供的装饰器和异步函数来使代码更清晰,就像这样
import React from 'react';
import { bind } from 'lodash';
import { wrap } from 'co';
import ajax from 'qajax';
function AutoBind(target, name, descriptor) {
let fn = descriptor.value;
delete descriptor.value;
delete descriptor.writable;
descriptor.get = function() {
return function () { fn.apply(this, arguments); }
}
}
export default class Foo extends React.Component {
constructor(props) {
super(props);
}
@AutoBind
async handleSubmit(event) {
event.preventDefault();
const Data = { foo: this.state.foo };
const Result = await ajax({ /* ... */ data: Data })
//...
}
}
后者的问题是teh handleSubmit函数内的this引用被设置为Window对象,因为编译后的输出绑定了_asyncToGenerator函数而不是提供的生成器回调函数。编译后的输出片段如下
_createDecoratedClass(Foo, [{
key: 'handleSubmit',
decorators: [AutoBind],
value: _asyncToGenerator(function* (event) {
event.preventDefault();
//...
})
}
我知道这是一个相当新的领域,这样的问题是可以预期的,我只是想知道是否有人尝试了类似的东西并找到了解决方案,暂时我会坚持以前的工作方法
最后,AutoBind装饰器在非异步函数上按预期工作,如此
@AutoBind
handleScreennameChange({ target: { value }}) {
this.setState({
screen_name: value
});
}