Reputation: 3219
I have been trying to figure out why this code doesn't bind to the class. In all cases of state
properties not being defined that I have read, it was due to a lack of the following line:
this.someFunction = this.someFunction.bind(this);
import React, { Component } from 'react';
import ReactDom from 'react-dom';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
import { Jumbotron } from "react-bootstrap";
import { Button } from "react-bootstrap";
import { Parallax, Background } from 'react-parallax';
import Fox from './fox.jpg';
var BASE_URL = "http://127.0.0.1:8080/";
var BIN_API = BASE_URL + "binter-info";
class App extends Component {
constructor(props) {
super(props);
this.state = {
tradingFrom: '...',
tradingTo: '...',
result: '...'
};
this.retrieveValue = this.retrieveValue.bind(this);
this.updateResult = this.updateResult.bind(this);
}
updateResult(str) {
var self = this;
if (str != null) {
self.setState({
result: str,
});
}
}
retrieveValue() {
var self = this;
console.log('App: retrieveValue executed...');
let symbol = this.state.tradingTo + this.state.tradingFrom;
// Make Server Request
axios.get(BIN_API, {
params: {
symbol: symbol,
}
}).then(function (response) {
console.log("Good");
//console.log(response);
self.updateResult(response.data);
console.log('this.state.result is now ' + this.state.result); // LINE 49
}).catch(function (error) {
console.log(error); // LINE 51
self.updateResult("ERROR");
});
}
render() {
return (
<div className="App">
<Parallax className='par'
blur={6}
bgImage={Fox}
bgImageAlt="Fox"
strength={200}
>
<h1>Welcome</h1>
<div style={{ height: '200px' }} />
</Parallax>
<Jumbotron>
<h2 className="App-Text">The following is a <strong>BETA_VERSION </strong>website.</h2>
</Jumbotron>
<Button className="App-Button" onClick={this.retrieveValue}> Retrieve Value </Button>
<div className="TXTAREA">
<p className="TA-p">{this.state.result}</p>
</div>
<Jumbotron>
<h1 className="App-Text">but wait..</h1>
</Jumbotron>
<Jumbotron>
<h1 className="App-Text">theres more!</h1>
</Jumbotron>
</div>
);
}
}
export default App;
My error is this:
App.js:51 TypeError: Cannot read property 'state' of undefined
at App.js:49
Upvotes: 0
Views: 61
Reputation: 10538
Your error is occuring because you are calling this.state
inside a Promise callback from Axios. this
will be undefined
.
console.log('this.state.result is now ' + this.state.result);
Note that you can avoid this by using arrow functions rather than the function expression syntax you are using. This will bind this
in the lexical context (lexical context meaning 'where the arrow function is defined' rather than 'where the function is called')
class App extends Component {
constructor(props) {
super(props);
this.state = {
tradingFrom: "...",
tradingTo: "...",
result: "..."
};
this.retrieveValue = this.retrieveValue.bind(this);
}
updateResult(str) {
var self = this;
if (str != null) {
self.setState({
result: str
});
}
}
retrieveValue() {
console.log("App: retrieveValue executed...");
let symbol = this.state.tradingTo + this.state.tradingFrom;
// Make Server Request
axios
.get(BIN_API, {
params: {
symbol: symbol
}
})
.then((response) => {
this.updateResult(response.data);
console.log("this.state.result is now " + this.state.result);
})
.catch((error) => {
console.log(error);
this.updateResult("ERROR");
});
}
render() {
return (
<div className="App">
<Button className="App-Button" onClick={this.retrieveValue}>
{" "}Retrieve Value{" "}
</Button>
<div className="TXTAREA">
<p className="TA-p">
{this.state.result}
</p>
</div>
</div>
);
}
}
Note that the pattern to bind
functions in the constructor of a React component is only used because when you pass in a function like you do in the onClick
handler:
onClick={this.retrieveValue}
You lose the this
context when it is called. The ways to solve this are to use bind
or arrow functions; the reason bind is used is because it avoids creating a new function object on each render
call. So, with that said, you do not need to bind
updateResult
.
EDIT: Note that this code concerns a previous revision of the OPs code, but the issue is the same.
Upvotes: 2