【问题标题】:bind(this) not working on ajax success functionbind(this)不适用于ajax成功功能
【发布时间】:2015-08-13 17:51:10
【问题描述】:

我使用 react 和 jQuery。这是我的代码的一部分。

在加载 react 组件之前,我执行 ajax 请求以了解用户是否已登录。

应该在响应返回状态码 200 时设置状态。
我是否错误地使用了bind(this)

componentWillMount: function(){
  $.ajax({
     url: "/is_signed_in",
     method: "GET",
     dataType: "json"
  }).success(function(response){
    this.setState({ signedIn: response.signed_in, currentUser: $.parseJSON(response.current_user) });
  }.bind(this));
},
componentDidMount: function(){
  console.log(this.state.signedIn);
}

编辑 01

当我在success(function(response){...}) 回调中执行console.log(this); 时。

this 是下面的。

R…s.c…s.Constructor {props: Object, context: Object, state: Object, refs: Object, _reactInternalInstance: ReactCompositeComponentWrapper}_reactInternalInstance: ReactCompositeComponentWrapper_context: Object_currentElement: ReactElement_instance: ReactClass.createClass.Constructor_isOwnerNecessary: false_isTopLevel: false_mountImage: null_mountIndex: 0_mountOrder: 2_pendingCallbacks: null_pendingElement: null_pendingForceUpdate: false_pendingReplaceState: false_pendingStateQueue: null_renderedComponent: ReactCompositeComponentWrapper_rootNodeID: ".0"_warnedAboutRefsInRender: false__proto__: ReactCompositeComponentWrappercontext: Object__proto__: Object__defineGetter__: __defineGetter__()__defineSetter__: __defineSetter__()__lookupGetter__: __lookupGetter__()__lookupSetter__: __lookupSetter__()constructor: Object()hasOwnProperty: hasOwnProperty()isPrototypeOf: isPrototypeOf()propertyIsEnumerable: propertyIsEnumerable()toLocaleString: toLocaleString()toString: toString()valueOf: valueOf()get __proto__: get __proto__()set __proto__: set __proto__()getDOMNode: ()__reactBoundArguments: null__reactBoundContext: ReactClass.createClass.Constructor__reactBoundMethod: ()arguments: (...)bind: (newThis )caller: (...)length: 0name: ""__proto__: ()[[TargetFunction]]: ()[[BoundThis]]: ReactClass.createClass.Constructor[[BoundArgs]]: Array[0]props: Objectrefs: Object__proto__: ObjectrenderButtonSet: ()setSignedIn: ()__reactBoundArguments: null__reactBoundContext: ReactClass.createClass.Constructor__reactBoundMethod: setSignedIn(response)arguments: (...)caller: (...)length: 1name: "setSignedIn"prototype: setSignedIn__proto__: ()<function scope>arguments: (...)bind: (newThis )arguments: (...)caller: (...)length: 1name: ""prototype: boundMethod.bind__proto__: ()<function scope>caller: (...)length: 1name: ""__proto__: ()[[TargetFunction]]: setSignedIn(response)[[BoundThis]]: ReactClass.createClass.Constructor[[BoundArgs]]: Array[0]state: ObjectcurrentUser: Objectcreated_at: "2015-07-24T18:30:38.772+09:00"email: "admin@gmail.com"facebook_account_url: nullfirstName: "유찬"github_account_url: nullgoogleplus_account_url: nullid: 1lastName: "서"linkedin_account_url: nullsns_avatar: nulltwitter_account_url: nullupdated_at: "2015-08-14T02:14:21.091+09:00"__proto__: ObjectsignedIn: true__proto__: Object__proto__: ReactClassComponent

解决方案
我上面的代码是反模式。
遵循答案 i 建议的方法之一。 另外,React 文档已经为我的案例提供了非常有用的解决方案:Load Initial Data via AJAX

另外,setState 是异步的。
这就是为什么我在控制台上登录时认为 setState 不起作用的原因。
毕竟,我检查了内部渲染并作为道具传递给子组件。

【问题讨论】:

  • 如果你只是将this 登录到控制台,你可以很容易地看到它到底是什么。
  • 附带说明:在 componentWillMount 中异步 setState 不是一个好主意,因为这会导致渲染竞争条件。
  • khuderm - 我更新了我的问题。 MikeDriver - 您对执行该操作的建议是什么?

标签: javascript jquery ajax reactjs


【解决方案1】:

我认为您不应该在 componentWillMount 中对 setState 使用 Ajax 调用; 在 componentDidMount 中执行

如果您不想在获得数据之前进行第一次渲染AND,这些数据仅用于初始化,请在外部执行您的调用,并在成功时使用获取的数据渲染您的视图 == ===>

<Myview data={initialDataFromTheCallSuccess} /> and then put it in getInitialState

如果您选择此路径,请阅读此内容(因为如文档中所述,这在某些条件下不是反模式):https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

希望对你有帮助

编辑: 有两种方法可以做到这一点,第一种方法是在反应类之外获取

  $.ajax({...}).success(function(res) {
      <MyView data={res} /> // render your function on success
  });

在 MyView 中,您从道具“数据”中获取初始状态。 仅当您需要调用一次 get 时才使用此方法(阅读反模式内容)。

其他方法正在执行您正在执行的操作,但在 componentDidMount 中。 https://facebook.github.io/react/tips/initial-ajax.html

希望更清楚

【讨论】:

  • 我没有 100% 明白你的意思。那么我该如何在componenetDidMount 中准确发送get 请求呢?我应该将this.state.signedIn 作为道具传递给子组件吗?你能告诉我任何示例代码吗?
  • 谢谢理查德。我想你的意思是第二种方法,因为 React Docs 提供了这个技巧,facebook.github.io/react/tips/initial-ajax.html
  • 我从来没有读过这个提示,但这正是我的意思:) 我将它添加到我的回答中
  • 大声笑但是.. 仍然绑定(这个)不工作 tho.. 虽然 this.state.signedIn 仍然是 null
  • setState 是异步的,console.log 在 render 或者 setState 回调 setState({...}, function() { console.log(this.state);});对于我不知道的绑定,请检查它是否正确编写以及您是否真的收到了一些东西:)