I'm having troubles setting state to the variable isCorrectAnswer
inside an axios call. I'm getting the error Cannot read properties of undefined (reading 'setState')
in the console log. What am I doing wrong?
Initial state of isCorrectAnswer
variable is constructor(props) {super(props)this.state = { isCorrectAnswer: false }}
and the axios call is
axios.post(
"API/path/to/ressource",
postData,
{
headers: {
"X-Access-Token":
"token",
},
}
)
.then(function (res) {
this.setState({
isCorrectAnswer: res.data.correct //Here im trying to change the state
}, () => console.log(this.state.isCorrectAnswer)) //and logging into console
})
.catch(function (error) {
console.log(error);
});
CodePudding user response:
When you call a function (non arrow function), this
is always an implicit parameter.
Normal functions
By normal functions I mean functions that are not methods.
In strict mode value of this
is always undefined
.
And in non strict mode value of this
is always the global object (window
in browsers)
function foo() {
"use strict";
return this;
}
function bar() {
return this;
}
console.log(foo() === undefined); // true
console.log(bar() === window); // true
Methods
this
refers to the object on which the method has been invoked.
function foo() {
"use strict";
return this;
}
const obj = { foo };
console.log(obj.foo() === obj); // true
And in your case the callback passed to then
is a normal function (not a method), so it's this
is set undefined
, hence you are getting an error.
Update to an arrow function and it would solve the issue because arrow functions don't have their own this
, in arrow functions this
is decided on the basis of lexical scope. Checkout the example below:
const getRandomNums = (delay) =>
new Promise((res) => setTimeout(() => res([5, 2, 3]), delay));
class App extends React.Component {
constructor() {
super();
this.state = { nums: [] };
}
componentDidMount() {
getRandomNums(1500).then((nums) => {
this.setState({ nums });
});
}
render() {
return <div>{JSON.stringify(this.state.nums, null, 2)}</div>;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<div id="root"></div>
CodePudding user response:
You can also do
Use arrow function instead of function
axios.post(
"API/path/to/ressource",
postData,
{
headers: {
"X-Access-Token":
"token",
},
}
)
.then((res) => {
this.setState({
isCorrectAnswer: res.data.correct //Here im trying to change the state
}, () => console.log(this.state.isCorrectAnswer)) //and logging into console
})
.catch((error) => {
console.log(error);
});