Reputation:
I have it working it will log the response to the console but then I can't set the distance to the state I will put all the code below.
getDist(dest){
var self = this;
var origin = this.state.location,
destination = this.state.dest,
service = new window.google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destination],
travelMode: window.google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false,
unitSystem: window.google.maps.UnitSystem.IMPERIAL
},
this.callback
);
}
callback(response, status) {
const self = this;
if(status === "OK") {
console.log(response);
var dest = response.destinationAddresses[0];
var dist = response.rows[0].elements[0].distance.text;
return response;
} else {
alert("Error: " + status);
}
}
ive tried to set the state in the callback function and it says that setState({})
is not a function. ive tried to set the state by doing this this.setState({ distFromLoc: self.callback })
but that just sets the call back function code to the state which is not what I want I have reached the end of my knowledge and the other web developer I work with makes no sense with our logic.
I just need to be able to set state for 2 seconds as im looping through a list of about 36 jobs and after every search it is going to check whether that job is close enough to the person searching or not.
Thanks in advance -Andy
Edit 1: I have edited my code it doesnt error any more but it still wont let me return the data would you be able to maybe show me what im doing wrong?
going to add the class that calls it, because it is saying that i cant use .then on a function to turn the function into a promise function.
updateSearchResults(data) {
this.setState({
searching: true,
});
var self = this;
var output = [];
console.log('Here we will search the db using user data for suitable jobs');
console.log('do some math to work out how many pagination we need for the amount of returned jobs and update the state accordingly');
data.forEach(item => {
console.log('before');
this.getDist(item.postcode).then(function (res){
console.log('after');
console.log(this.state.distFromLoc);
if (this.state.location === '') {
if (item.option === 'Part Time' && this.state.partTime && !this.state.weekend){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('1');
output.push(item)
} else if (this.state.keywords === ''){
console.log('2');
output.push(item);
}
} else if (item.option === 'Weekends' && this.state.weekend && !this.state.partTime){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('3');
output.push(item)
} else if (this.state.keywords === ''){
console.log('4');
output.push(item);
}
} else if (item.option === 'both' && this.state.weekend && this.state.partTime){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('5');
output.push(item)
} else if (this.state.keywords === ''){
console.log('6');
output.push(item);
}
} else if (!this.state.weekend && !this.state.partTime) {
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('7');
output.push(item)
} else if (this.state.keywords === ''){
console.log('8');
output.push(item);
}
}
} else if (this.state.distFromLoc <= this.state.distance) {
console.log(this.state.distFromLoc);
console.log(this.state.distance);
if (item.option === 'Part Time' && this.state.partTime && !this.state.weekend){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('9');
output.push(item)
} else if (this.state.keywords === ''){
console.log('10');
output.push(item);
}
} else if (item.option === 'Weekends' && this.state.weekend && !this.state.partTime){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('11');
output.push(item)
} else if (this.state.keywords === ''){
console.log('12');
output.push(item);
}
} else if (item.option === 'both' && this.state.weekend && this.state.partTime){
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('13');
output.push(item)
} else if (this.state.keywords === ''){
console.log('14');
output.push(item);
}
} else if (!this.state.weekend && !this.state.partTime) {
if (item.title.toLowerCase().match(this.state.keywords.toLowerCase()) !== null ) {
console.log('15');
output.push(item)
} else if (this.state.keywords === ''){
console.log('16');
output.push(item);
}
}
}
})
.catch(function (err){
console.log(err);
});
});
window.setTimeout(function() {
self.setState({
dataToShow: output,
searching: false,
current: 1,
});
const dataLength = self.state.dataToShow.length
self.setState({
amountOfJobs: dataLength
})}, 10000)
}
getDist(dest){
var self = this;
const wrappedCallback = (...args) => this.callback(...args);
var origin = this.state.location,
destination = dest,
service = new window.google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [origin],
destinations: [destination],
travelMode: window.google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false,
unitSystem: window.google.maps.UnitSystem.IMPERIAL
}, wrappedCallback
);
}
callback(response, status) {
const self = this;
if(status === "OK") {
console.log(response);
var dest = response.destinationAddresses[0];
if (response.rows[0].elements[0].status === "ZERO_RESULTS"){
} else if (response.rows[0].elements[0].status === "OK"){
var dist = response.rows[0].elements[0].distance.text;
this.setState({
distFromLoc: dist
})
}
} else {
alert("Error: " + status);
}
}
i know im doing something wrong i just cant work out what it is exactly.
current error im getting is this TypeError: Cannot read property 'then' of undefined why cant i put a promise on the function.
Upvotes: 0
Views: 2031
Reputation: 369
There might be an alternative solution, but it uses a global variable:
window.callback = function( ) {};
window.callback = (code, name) => {
me.setState({stateVariable: code});
};
You might change this code accordingly and use the callback in any place of your code (because it was declared globally with an arrow function that preserves context, it is a closure)
Upvotes: 0
Reputation: 5188
This is a binding problem and one of the main reasons to avoid using classes in javascript. Here's where your problem is:
service.getDistanceMatrix({
origins: [origin],
destinations: [destination],
travelMode: window.google.maps.TravelMode.DRIVING,
avoidHighways: false,
avoidTolls: false,
unitSystem: window.google.maps.UnitSystem.IMPERIAL
},
this.callback
);
When you provide the callback as this.callback
, you're passing in a function. When that function gets called, however, it no longer has the context it needs to know what this
actually is, because the calling code is now in Google's API. There's 3 solutions to this problem.
1) Bind the function so that it knows what this
is
//boundCallback will now always have the correct value for "this"
const boundCallback = this.callback.bind( this );
2) Wrap it in a fat arrow function (ES6 only)
//fat arrow always takes the value of "this" from surrounding scope
const wrappedCallback = (...args) => this.callback(...args);
3) Use React.createClass()
for your component
This is my preferred solution - if you create your component with React.createClass()
instead of using class Comp extends React.Component
, all the functions are automatically bound for you, so you never need to mess about - this.callback
is always correct.
Upvotes: 1