我在componentDidMount方法中获取组件的数据,如下所示:
componentDidMount() {
this.getSomeData();
}
这是getSomeData方法本身:
getSomeData() {
var that = this;
var setState2 = this.setState;
var setState3 = this.setState.bind(this);
axios.get('/someurl').then(function(response) {
that.setState({ data: response.data }); // option A
setState2({ data: response.data }); // option B
setState3({ data: response.data }); // option C
});
}
'选项A'和'选项C'工作得很好,但是'选项B'抛出并且错误说'updater'方法不能在'undefined'上调用,这意味着'this'上下文的含义是setState里面错了。好的,在'选项C'中'this'的值是绑定的并且它可以工作,但有人可以解释为什么工作'选项A'不受约束?非常感谢!
答案 0 :(得分:0)
var that = this;
var setState2 = this.setState;
var setState3 = this.setState.bind(this);
axios.get('/someurl').then(function(response) {
// Here, you are invoking setState as a method of `that`, which
// above was defined as `this`, creating a closure in this function
that.setState({ data: response.data });
// setState2 is an unbound function reference, as you assigned it to
// the function setState directly above, but didn't call bind() on it
// thus, this function has no idea of what `this` is and so it's undefined
setState2({ data: response.data }); // option B
// setState3 is a bound function. it has captured the value of `this` above, and so will provide it to the body of the function it has been bound to
setState3({ data: response.data }); // option C
});
我希望能够解决问题
答案 1 :(得分:0)
对于选项A,您在变量this
中存储了that
上下文的引用,然后使用that.setState
,允许您获取上下文而不将其绑定到任何位置。
在另一个变量中存储对上下文的引用是在回调中丢失上下文的常见解决方案。这是JavaScript的一般行为,不仅限于React。
使用arrow functions in ES6,您可以消除这些绑定“变通办法”,因为回调中不会更改this
上下文。
axios.get('/someurl').then((response) => {
this.setState({ data: response.data }); // option A
});
答案 2 :(得分:0)
选项A:您在that
上调用了setState,该地址被定义为外部this
- >所以它是回调中的一个闭包。
选项B: setState2
是对不再具有" context"的函数的引用。 - 所以它没有约束力。执行该函数后,它不知道this
的含义(参见下面的示例)
选项C: setState3
与setState2
类似,但它确实知道this
是什么,并且可以从中获取它。< / p>
<强>建议强>:
this
的值,因此您永远不必重新分配var that = this
)将您的类方法声明为匿名箭头函数,以保持对此的访问(在React组件中特别有用):
getSomeData = () => {
// ...
};
示例:强>
class Test {
constructor() {
this.name = 'Test class';
}
setState(res) {
console.log('this', this);
try {
console.log('Class: ', this.name);
console.log('setState', res);
} catch (e) {
console.warn('Ups! Something went wrong', e);
}
}
getSomeData() {
var that = this;
var setState2 = this.setState;
var setState3 = this.setState.bind(this);
var fakeResponse = {
data: 'I came from the Internet!',
};
(function fakeAsync(response) {
// option A
console.group('Option A');
that.setState({
data: fakeResponse.data
});
console.groupEnd();
// option B
console.group('Option B');
setState2({
data: fakeResponse.data
});
console.groupEnd();
// option C
console.group('Option C');
setState3({
data: fakeResponse.data
});
console.groupEnd();
})(fakeResponse);
}
}
const test = new Test();
test.getSomeData();
&#13;
如果你在控制台中查看,你会看到:
Option A
this Test {name: "Test class"}
Class: Test class
setState Object {data: "I came from the Internet!"}
Option B
this undefined
Ups! Something went wrong TypeError: Cannot read property 'name' of
undefined
at setState (VM272:53)
at fakeAsync (VM625:75)
at Test.getSomeData (VM273:81)
at window.onload (VM503:87)
Option C
this Test {name: "Test class"}
Class: Test class
setState Object {data: "I came from the Internet!"}