I'm new in React and I'm trying to write an app working with an API. I keep getting this error:
TypeError: this.setState is not a function
when I try to handle the API response. I suspect it's something wrong with this binding but I can't figure out how to fix it. Here's the code of my component:
var AppMain = React.createClass({ getInitialState: function() { return{ FirstName: " " }; }, componentDidMount:function(){ VK.init(function(){ console.info("API initialisation successful"); VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }); }, function(){ console.info("API initialisation failed"); }, '5.34'); }, render:function(){ return ( <div className="appMain"> <Header /> </div> ); } });
This error happens when JavaScript can't find the setState() function from the context of this keyword. There are two ways to fix this error: Declare the class method using the arrow function syntax. Bind the class method reference during constructor call or inside the calling property.
The React. js "Uncaught TypeError: X is not a function" occurs when we try to call a value that is not a function as a function, e.g. calling the props object instead of a function. To solve the error, console. log the value you are calling and make sure it is a function.
useState returns the current state and a function to update it. But this function updates the value in an asynchronous way. That means by calling that function, the variable is not going to change immediately.
The setState() Method State can be updated in response to event handlers, server responses, or prop changes. This is done using the setState() method. The setState() method enqueues all of the updates made to the component state and instructs React to re-render the component and its children with the updated state.
The callback is made in a different context. You need to bind
to this
in order to have access inside the callback:
VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }.bind(this));
EDIT: Looks like you have to bind both the init
and api
calls:
VK.init(function(){ console.info("API initialisation successful"); VK.api('users.get',{fields: 'photo_50'},function(data){ if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } }.bind(this)); }.bind(this), function(){ console.info("API initialisation failed"); }, '5.34');
You can avoid the need for .bind(this) with an ES6 arrow function.
VK.api('users.get',{fields: 'photo_50'},(data) => { if(data.response){ this.setState({ //the error happens here FirstName: data.response[0].first_name }); console.info(this.state.FirstName); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With