我使用react从parse中检索数据,在我自己的函数中操作它,然后更新渲染中的组件。
问题是我无法在我自己的复杂函数中更新状态,除非我附加了一串bind(this)。整个组件如下所示:
React.Component({
getInitialState: function () {
return{
isloading:true
}
},
componentDidMount: function(){
this.myStupidFunction()
},
myStupidFunction : function(){
(
(
(nested parse queries that eventually ...
return an object and set isloading:false).bind(this))
.bind(this))
.bind(this)
},
render: function (){
if (this.state.isloading) {
return(
<Text "...isloading"/>
)
} else {
return(
...actually return important stuff...
)
}
}
})
更聪明的方法是什么?我是否需要为每个嵌套函数真正.bind(this)?
答案 0 :(得分:3)
有几种方法可以维护组件的上下文。
如果使用ES6箭头定义功能。无论函数如何被调用,箭头函数都强制将其内部上下文与外部上下文相同。
parse.find({
success: results => {
// this is correct
console.log(this);
}
});
我认为这是最优雅的解决方案,但是not all browsers support arrow functions yet。
React会自动将this
绑定到组件的每个顶级方法中。他们总是保证有正确的背景。
onSuccess: function() {
// this is correct
console.log(this);
},
componentWillMount: function() {
parse.find({
success: this.onSuccess
});
}
在我看来,这也相当优雅。它让React在你编写代码时处理上下文的混乱。但是,这可能意味着您最终会在组件的顶层使用太多方法,因此请谨慎使用。
某些函数(例如map
)允许您可选地传递上下文以用作this
作为最终参数。这使您可以在没有.bind(this)
的情况下维护正确的上下文。
data.map(function() {
console.log(this);
// this is correct
}, this);
这仅适用于某些方法,因此它不是真正的通用解决方案。
this
创建对此的引用并改为使用它。
var __this__ = this;
parse.find({
success: results => {
// __this__ is correct
console.log(__this__);
}
});
这个hack在Javascript中一直存在,但我不认为这是解决问题的好方法。
对于那些喜欢Javascript的人来说,你也可以使用ES7 function bind syntax proposal来实现这一目标 - 目前已在Babel中实施。
parse.find({
success: this::function(results) {
// this is correct
console.log(this);
}
});
这需要使用ES7的实验提案阶段功能。您可能不想开始使用它,但是要注意这一点非常有趣。左侧的值将绑定到右侧的函数中,如this
。
答案 1 :(得分:0)
在函数开头使用closure来捕获this
。它可以在任何嵌套结构中使用。这种闭包的常规名称是self
_this
和that
。我更喜欢self
。
myStupidFunction : function(){
var self = this;
someAsyncCall(1,2, function(result) {
//some nested stuff
anotherAsyncCall(1,2 function(innerResult) {
self.setState(innerResult);
});
});
}
答案 2 :(得分:0)
一个解决方案可能是使用局部变量
myStupidFunction:function(){
var that=this
ParseReact.Mutation.Create('Place', {
name: 'New Place',
user: Parse.User.current()
})
.dispatch()
.then(function() {
that.refreshQueries();
});
}
答案 3 :(得分:0)
使用ES7 Property Initalizer语法,目前在Babel中实现。
关键是methodName = () => { //method return }
您可以阅读更多here。
import React from 'react';
export default class Note extends React.Component {
constructor(props) {
super(props);
this.state = {
editing : false
}
}
render() {
const editing = this.state.editing;
return (
<div>{ editing ? this.renderEdit() : this.renderTask() }</div>
)
}
renderEdit = () => {
return (
<input type="text"
className="edit-input"
autoFocus={true}
defaultValue={this.props.task}
onBlur={this.finishEdit}
onKeyPress={this.checkEnter} />
)
}
renderTask = () => {
const onDelete = this.props.onDelete;
return (
<div onClick={this.edit}>
<span className="task-body">{this.props.task}</span>
{ onDelete ? this.renderDelete() : null }
</div>
)
}
renderDelete = () => {
return (
<button className="delete-btn" onClick={this.props.onDelete}>x</button>
)
}
edit = () => {
this.setState({
editing : true
})
}
checkEnter = (e) => {
if(e.key === "Enter") {
this.finishEdit(e);
}
}
finishEdit = (e) => {
this.props.onEdit(e.target.value);
this.setState({
editing : false
})
}
}
&#13;
//注意:上面项目中的示例类。