6

I use react and jQuery. here's a part of my code.

Before react component mounts, I perform ajax request to know if user is logged in.

It is supposed to set state when a response returns status code 200.
am I incorrectly using 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);
}

Edit 01

when I do console.log(this); in success(function(response){...}) callback.

this was the below.

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

Solutions
My code above was antipattern.
Follow one of the methods suggested by Answer i adopted. Plus, React documentation already provided very useful solution about my case: Load Initial Data via AJAX

Also, setState is asynchronous.
That's why I thought setState not working when I log it on console.
After all, i checked inside render and pass as props to child components.

seoyoochan
  • 822
  • 3
  • 14
  • 28

1 Answers1

5

I think you shouldn't use an Ajax call for setState in componentWillMount; do it in componentDidMount.

If you don't want to do the first render before you're having data AND those data are just for initialization perform your call outside and on success render your view with the fetched data =====>

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

Read this if you choose this path (cause as stated in the doc this is not an anti-pattern on certain conditions): https://facebook.github.io/react/tips/props-in-getInitialState-as-anti-pattern.html

hope it helps

Edit: There is two way to do it the first one you fetch outside your react class

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

and in MyView you getInitialState from props "data". Use this method only if you need to call your get once (read the anti-pattern stuff).

Other method is doing what you are doing but in componentDidMount. https://facebook.github.io/react/tips/initial-ajax.html

Hope it's clearer

Clomp
  • 3,168
  • 2
  • 23
  • 36
François Richard
  • 6,817
  • 10
  • 43
  • 78
  • I did not quite 100% get your meaning. Then how do I exactly send get request in `componenetDidMount`? and should I pass `this.state.signedIn` to child components as props? Could you show me any sample code? – seoyoochan Aug 13 '15 at 20:00
  • Thank you Richard. I think you mean the second method as this tip provided by React Docs, https://facebook.github.io/react/tips/initial-ajax.html – seoyoochan Aug 13 '15 at 20:11
  • I never read this tip but that's exactly what I meant :) I added it to my answer for others – François Richard Aug 13 '15 at 20:12
  • lol but.. still bind(this) not working tho.. although `this.state.signedIn` is still `null`. – seoyoochan Aug 13 '15 at 20:47
  • setState is asynchronous, console.log in render or in setState callback setState({...}, function() { console.log(this.state);}); For the binding I don't know check it's written properly and that you're really receiving something :) – François Richard Aug 13 '15 at 20:52