I am creating a sensor app, where I have to update the state regular in a time interval of 15 seconds with the data receiving from the backend. Eventhough I can get the data successfully from the backend in the time interval, I cannot update the state in ReactJS. The code is as follows:
async regularCallAPI(){
let result;
const url = "http://..../...";
await fetch(url).then( res => res.json()).then( res => { result = res});
console.log("Regular Data from Backend : ", result);
let updatedSensors = result.map( sensor => {
return {
floorNum: sensor.floor_no,
roomNum: sensor.room_no,
sensorStatus: sensor.sensor_status,
alertStatus: sensor.alert_status,
ownerName: sensor.owner_name,
email: sensor.email,
phoneNumber: sensor.phone_number,
recordedDateAndTime: new Date(sensor.created_date).toLocaleString()
}
});
await this.setState({ sensors: updatedSensors });
console.log("sensor state updated ...");
}
and I have executed the above function in a interval of 15 seconds ;
timerId = setInterval(this.regularCallAPI, 15000);
The problem I have is, it runs the first time successfully and then when it run the second time, I get this error:
Unhandled Rejection (TypeError): this.setState is not a function
and yes, the function is already binded to the component in the constructor. What is the reason for this behavior and what is the possible solution for this ?
The callback is made in a different context. You need to bind to this in order to have access inside the callback:
setInterval( () => this.regularCallAPI(), 15000);
Related
Havent been able to reconcile this challenge to the docs :/ Hoping someone can point out to me why when this lwc renders (successfully) and it receives an event via its empApi subscription it throws a 'handleGoNext is not defined' runtime error. I appreciate the function is not visible, but I'm not able to construct things such that a resulting function call is able to be made successfully. Calling this.handleGoNext() doesnt work either. Any pointers would be most appreciated!
handleGoNext(){
// *** this is the logic Im hoping to call ***
};
// Initializes the component
connectedCallback() {
if(this.subscription = {}){
// Callback invoked whenever a new event message is received
const messageCallback = function (response) {
handleGoNext(); // *** THIS IS THE CALL THAT BREAKS THINGS ***
};
// Invoke subscribe method of empApi. Pass reference to messageCallback
subscribe(this.channelName, -1, messageCallback).then((response) => {
// Response contains the subscription information on subscribe call
console.log(
'Subscription request sent to: ',
JSON.stringify(response.channel)
);
this.subscription = response;
});
}
}
what happens when you do subscribe(this.channelName, -1, this.handleGoNext)?
Here's my function from around Easter time, didn't check recently if it still works.
isSubscribed = false;
subscription = {};
replayId;
#track data = [];
subscribe(id) {
const handleMessage = (response) => {
let val = Object.assign({}, response.data.event, response.data.payload);
this.replayId = Math.max(this.replayId ?? 0, val.replayId);
/* do not use this.data.push(val);
it doesn't play well with datatable. Use the spread operator or JSON.parse/JSON.stringify trick.
Plus we want new rows to be added on top of the list.`
*/
this.data = [val, ...this.data];
};
subscribe(this.channel, id, handleMessage).then((response) => {
this.subscription = response;
this.isSubscribed = true;
});
}
I am working on google extensions. I am trying to process message passing between my popup.tsx and background.ts
Before sending message from my background.ts, I print the data. Data exist. However, in my popup.tsx chrome.runtime.onMessage not triggered. I dont understand which function not working and what is the problem. I examine lots of example but result still the same. What is the problem? I am adding my message passing codes..
Here is my background.ts runtime.sendMessage func. this function is inside another function that is called 'collectData'. When I open new tab or update the tab, this function triggered and works. Everytime this data works stable. I can see the data in every page.
chrome.runtime.sendMessage({
msg: 'url_data',
data: data,
})
Then, I am trying to receive the data in my popup.tsx with runtime.onMessage. When I reset the extension, it works sometimes just once, then that onMessage func not working at all :
const [requestData, setRequestData] = useState<string>()
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log(' popup runtime on message req', request)
if (request.msg === 'url_data') {
checkWebsite(request.data).then((res) => {
console.log('popup data alındı')
console.log('popu res', res)
setRequestData(res)
// chrome.runtime.sendMessage({
// msg: 'res_length',
// data: res.matches.length,
// })
// console.log('popup data res length gönderildi')
// res.matches.length === 0 ? setIsSecure(true) : setIsSecure(false)
setHost(request.data.hostname)
})
sendResponse({ message: 'res length sended' })
console.log('res length response send')
}
})
Everytime, I change request data state. If it changes, I want to update popup with useEffect.
useEffect(() => {
console.log('useeffect', requestData)
}, [requestData])
As a result, for the first the main problem is message passing. Why it is not working?
I am trying to call the "getData" API over and over for each value in the "myArray" variable. Each time it gets new data from the "getData" call, I am trying to push the result to an array so I can manipulate the values in the "destinationArray" section of code. However, since typescript is not async, it gets to the "destinationArray" code before it's finished in the .subscribe / before it's finished iterating.
I've already tried fixing this with await waitUntil(() => done==true, { timeout: 10015 });
but I keep getting randomly appearing messages in the console saying ERROR Error: Uncaught (in promise): Error: Timed out after waiting for 10015 ms. The naive answer is to just increase the timeout to infinity, but the actual API call itself does not take 10 seconds, it takes about 1 second (if even that long). How can I make it wait until it's finished iterating / subscribing before it moves onto the "destionationArray" section at the bottom, without seeing that timeout error message in the console?
let dataFromAPIcall: any[] = []
let myArray: any[] = ["hello","world"]
for(let i = 0; i< myArray.length; i++) {
this.GetDataSubScription = this.myService.getData(myArray[i]).pipe( takeUntil(this.ngUnsubscribe) ).subscribe(data => {
dataFromAPIcall.push(data)
if(i+1 == myArray.length) {
done = true
}
});
}
await waitUntil(() => done==true, { timeout: 10015 });
let destinationArray: any[] = [];
for(let i = 0; i < dataFromAPIcall.length; i++) {
destinationArray[i] = [dataFromAPIcall[i].something1, dataFromAPIcall[i].something2]
}
You can zip your api calls and handle all responses in a reactive way, without using imperative state variables:
After all observables emit, emit values as an array
// creating an array of observables. The requests are not fired yet.
const requests = myArray.map(i => this.myService.getData(i));
const destinationArray: any[] = [];
// passing the request array to the zip function.
// this will actual initiate the requests and emit when ALL
// requests are done
zip(...requests).pipe(
tap(responses => {
// maping responses to destinationArray
destinationArray = responses.map(dataFromAPIcall => [dataFromAPIcall.something1, dataFromAPIcall.something2])
}),
tap(_ => {
// continue here
})
).subscribe();
i have a simple input form where i put a list of strings , then for each element of the string (string[i]) i run an ajax Get request to my api .
so here is the ajax request :
async function getUsers(props){
try{
const response = await Axios.get(`url=`+props)
console.log(response)
return response;
}catch{
console.log("response failed")
}
}
and i run it here :
... some code here ...
for(var i =0; i < string.length; i++){ // map the entery (string)
getUsers(string[i]).then(res => {
this.setState({
string2:res // this one is just for testing
});
console.log(res.data.id);
mystring22.push({res});
console.log("me inside the promise : " + this.state.string2.data.id);
})
setTimeout(() => {
console.log("iam not empty " + this.state.string2.data.id);
console.log(mystring22);
/* -----------------
I WANT TO DO SOME WORK HERE
-----------------*/
}, 3000);
this.setState({
string3 : mystring22
})
... some code here ...
so everything works fine , and my problem is the following :
the code take too much time (3 second for each request ) , is there is a way to change the code so it can do "SOMETHING" after each request , i tried to delete the setTimeout or reduce it but that not working the array is undefined after that .
hope you can help me .
thank you
setState is an async function, so when you call:
setState({ string2: res });
this.state.string2; // OUTDATED
in order to access the updated value, you must use the callback:
setState({ string2: res },
() => { console.log(this.state.string2) }); // UP TO DATE
as you can see in this codesandbox example, with the callback on line 27 and without the callback on 33.
I have been using firebase realtime database to store really simple data. Listeners are set on the complementary lifecycle events. Everything works okay most of the time. Rarely the callback snapshot takes longer than its average 1-2 seconds but it eventually does respond after 30 or 40 seconds. This is, however, is not a network issue and only occurs on windows clients.
componentDidMount() {
this.folderRef = db.ref(`folders/${this.props.user}`)
this.listRef = db.ref(`lists/${this.props.user}`)
this.folderListener = this.folderRef.on('value', (snapshot) => {
//this won't fire randomly
this.props.getFolderTree(snapshot.val())
})
this.listListener = this.listRef.on('value', (snapshot) => {
//this won't fire randomly
this.props.getList(snapshot.val())
})
}
componentWillUnmount() {
if (this.folderListener) {
this.folderRef.off('value', this.folderListener)
this.folderListener = null
}
if (this.listListener) {
this.listRef.off('value', this.listListener)
this.listListener = null
}
}
I wondered if someone who had similar behaviour on firebase value callbacks could share the same insight on how they resolved the issue.
Edit: identical to this issue