Calling a function in setInterval gives error in react native - javascript

I am working on a React Native app where I'm trying to call a function in setInterval to re-render component in every three seconds. But when I put the function in setInterval it returns the error this.refreshData() is not a function. Here's the code for this I'm having:
refreshData = async()=> {
await fetch('https://myapi', {
method: 'GET',
})
.then((response) => response.json())
.then((response) => {
this.setState({ tableData1: response.First })
this.setState({ tableData2: response.Special })
this.setState({ tableData3: response.Consolidation })
})
}
componentWillMount() {
const { navigation } = this.props;
this.focusListener = navigation.addListener("didFocus", () => {
var today = new Date()
var time = today.getHours()
console.log(today.getMinutes())
var weekDay = today.getDay()
if ((time >= 22) && (time <= 23 )){
if(today.getMinutes()<=30){
setInterval(function() {
this.refreshData()
}, 3000);
}
});
}
How this error can be resolved?

Use arrow function.
Try this example:
function refreshData(){
console.log("called");
}
setInterval(() => {
this.refreshData();
}, 3000);

Either bind the setTimeout/setInterval function or use Arrow function i.e
setTimeout(function() { //or setInterval(whatever you need to use)
this.refreshData()
}, 3000);
}
}).bind(this);
or
setTimeout(() => { //or setInterval(whatever you need to use)
this.refreshData();
}, 3000);

Related

using interval inside componentDidMount() in react native

Please, how do I use interval inside componentDidMount in react native?
I want to call receiveData in interval when componentMounts
time:date.now is there just from example, I dont know how to replace it with my function for it to work
componentDidMount() {
this.interval = setInterval(() => this.setState({ time: Date.now() }), 1000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
receiveData = () => {
this.socket.on('data', (data) =>{
console.log("recieved data: " + data);
this.distanceR = data;
});
}

Synchronisation problem using rxjs and old style callbacks

I have old-style library with 4 asynchronous functions - lets call them libA, libB, libC, libD (the running time of each is unknown/random) - when they finish they call my callback
I write loadString function which return observable (which should contains results of each callback function - I use string here for simplicity but it can be array of results) but it gives wrong result "AADDDDD". The expected result is "AADDDDDCCCCBBB". How to do it right using rxjs?
function loadString() {
let result = '';
return Observable.create(observer =>{
libA( n=> { result+='A'.repeat(n) });
libB( n=> { result+='B'.repeat(n) });
libC( n=> { result+='C'.repeat(n) });
libD( n=> {
result+='D'.repeat(n);
observer.next(result);
});
})
}
Below there is working snippet which you can copy to your answer and develop loadString function
// SET-UP
const { of, Observable } = rxjs;
const { map, switchMap, delay } = rxjs.operators;
// simulated lib function - not change this (the times are random)
function libA(callback) { setTimeout( _=>callback(2), 1000); }
function libB(callback) { setTimeout( _=>callback(3), 3000); }
function libC(callback) { setTimeout( _=>callback(4), 2000); }
function libD(callback) { setTimeout( _=>callback(5), 1500); }
// QUESTION: how to write below function body using rxjs?
function loadString() {
let result = '';
return Observable.create(observer =>{
libA( n=> { result+='A'.repeat(n) });
libB( n=> { result+='B'.repeat(n) });
libC( n=> { result+='C'.repeat(n) });
libD( n=> {
result+='D'.repeat(n);
observer.next(result);
});
})
}
// TEST
let s = loadString().subscribe(str=> {
console.log(str); // wrong result: I expected "AADDDDDCCCCBBB" value
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>
UPDAE
I would like to not run lib functions in sequential way but parallel (they send some requests to API...)
A hacked together solution that illustrates your problem - you should only call observer.next after your last callback has been called. Just keep a running count. The below code isn't important, the knowledge of, "just wait until your last one gets called before emitting" is the key.
Here's the hacked together solution for the fun of it:
// SET-UP
const { of, Observable } = rxjs;
const { map, switchMap, delay } = rxjs.operators;
// simulated lib function - not change this (the times are random)
function libA(callback) { setTimeout( _=>callback(2), 1000); }
function libB(callback) { setTimeout( _=>callback(3), 3000); }
function libC(callback) { setTimeout( _=>callback(4), 2000); }
function libD(callback) { setTimeout( _=>callback(5), 1500); }
// QUESTION: how to write below function body using rxjs?
function loadString() {
let result = '';
const done = (observer,count) => val => {
result += val;
// THIS IF STATEMENT IS WHAT YOU WERE MISSING
if(!--count) return observer.next(result);
}
return Observable.create(observer =>{
const complete = done(observer,4);
libA( n=> complete('A'.repeat(n))),
libB( n=> complete('B'.repeat(n))),
libC( n=> complete('C'.repeat(n))),
libD( n=> complete('D'.repeat(n)));
})
}
// TEST
let s = loadString().subscribe(str=> {
console.log(str); // wrong result: I expected "AADDDDDCCCCBBB" value
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>
Call each libX function from the callback of the previous one.
function loadString() {
let result = '';
return Observable.create(observer => {
libA(n => {
result += 'A'.repeat(n);
libB(n => {
result += 'B'.repeat(n);
libC(n => {
result += 'C'.repeat(n);
libD(n => {
result += 'D'.repeat(n);
observer.next(result);
});
});
});
})
});
}
libD is the ONLY thing that calls observer.next. As soon as that finishes, your observable will emit, even if the other ones haven't finished. So you need to wait. Try combineLatest (although that won't preserve order)?
// SET-UP
const { of, Observable, combineLatest } = rxjs;
const { map, switchMap, delay } = rxjs.operators;
// simulated lib function - not change this (the times are random)
function libA(callback) { setTimeout( _=>callback(2), 1000); }
function libB(callback) { setTimeout( _=>callback(3), 3000); }
function libC(callback) { setTimeout( _=>callback(4), 2000); }
function libD(callback) { setTimeout( _=>callback(5), 1500); }
// QUESTION: how to write below function body using rxjs?
function loadString() {
let result = '';
return combineLatest(
Observable.create(observer => libA(n => observer.next('A'.repeat(n)))),
Observable.create(observer => libB(n => observer.next('B'.repeat(n)))),
Observable.create(observer => libC(n => observer.next('C'.repeat(n)))),
Observable.create(observer => libD(n => observer.next('D'.repeat(n))))
);
}
// TEST
let s = loadString().subscribe(str=> {
console.log(str); // wrong result: I expected "AADDDDDCCCCBBB" value
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>
We can also use bufferCount (technique from here )
// SET-UP
const { Subject } = rxjs;
const { take, bufferCount, map, finalize } = rxjs.operators;
// simulated lib function - not change this (the times are random)
function libA(callback) { setTimeout( _=>callback(2), 1000); }
function libB(callback) { setTimeout( _=>callback(3), 3000); }
function libC(callback) { setTimeout( _=>callback(4), 2000); }
function libD(callback) { setTimeout( _=>callback(5), 1500); }
function loadString() {
let result = new Subject();
libA( n=> { result.next('A'.repeat(n)); });
libB( n=> { result.next('B'.repeat(n)); });
libC( n=> { result.next('C'.repeat(n)); });
libD( n=> { result.next('D'.repeat(n)); });
return result.pipe(
bufferCount(4), // num of callbacks
take(1), // this will unsubscribe after 4 values received
map( r => r.join`` ),
);
}
// TEST
let s = loadString().subscribe(str=> {
console.log(str); // wrong result: I expected "AADDDDDCCCCBBB" value
}, e=>{}, ()=> console.log('final'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>
or less efficient scan (because it concat strings not once but everytime some task ends)
// SET-UP
const { Subject } = rxjs;
const { scan, take, last, map } = rxjs.operators;
// simulated lib function - not change this (the times are random)
function libA(callback) { setTimeout( _=>callback(2), 1000); }
function libB(callback) { setTimeout( _=>callback(3), 3000); }
function libC(callback) { setTimeout( _=>callback(4), 2000); }
function libD(callback) { setTimeout( _=>callback(5), 1500); }
function loadString() {
let result = new Subject();
libA( n=> { result.next('A'.repeat(n)); });
libB( n=> { result.next('B'.repeat(n)); });
libC( n=> { result.next('C'.repeat(n)); });
libD( n=> { result.next('D'.repeat(n)); });
return result.pipe(
take(4),
scan((acc, value) => acc + value),
last()
);
}
// TEST
let s = loadString().subscribe(str=> {
console.log(str); // wrong result: I expected "AADDDDDCCCCBBB" value
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.5/rxjs.umd.min.js" integrity="sha256-85uCh8dPb35sH3WK435rtYUKALbcvEQFC65eg+raeuc=" crossorigin="anonymous"></script>

How figure out calling function setTimeout function at react

i have a react functional component.
Here is i have getData function, with this function i'm getting some data from api and then if data have i wan't to call anotherFunc();, But i wan't to do that after 3 second. I tried to put there setTimeout function but it's worked directly not wait 3 second. What i need to do?
function Hello(props) {
anotherFunc = () => {
console.log('hello');
}
const getData = () => {
let data = {
id: 1
}
axios.post(baseUrl, data).then(res => {
if (res.data) {
setTimeout(() => {
anotherFunc();
}, 3000);
}
});
}
return <h1>Something</h1>;
}
export default Hello;

How to clear interval after status change in an API response?

Let's say I have a checkStatus() method which is triggered after a response to an endpoint is successful. Inside this there is a setInterval like so:
checkStatus() {
setInterval(() => {
client
.query({
query,
variables,
})
.then(res => {
if (res.status) {
console.log("FINISHED!");
}
});
}, 3000);
}
Basically I am querying an endpoint every 3 seconds. Once the res.status becomes true, I want to clear the interval. The component is still there and hasn't unmounted yet.
How do I achieve this?
Just clear interval in your check condition.
Example:
checkStatus() {
const interval = setInterval(() => {
client
.query({
query,
variables,
})
.then(res => {
if (res.status) {
console.log("FINISHED!");
clearInterval(interval)
}
});
}, 3000);
}
Basically you need to assign a value to the setInterval function and clear it into your callback:
checkStatus() {
const intervale = setInterval(() => {
client
.query({
query,
variables,
})
.then(res => {
if (res.status) {
console.log("FINISHED!");
clearInterval(intervale)
}
});
}, 3000);
}
You need to first store the reference returned by setInterval and pass it to clearInterval to clear it. For example, storing the reference in a variable ref -
checkStatus() {
const ref = setInterval(() => {
client
.query({
query,
variables,
})
.then(res => {
if (res.status) {
clearInterval(ref);
console.log("FINISHED!");
}
});
}, 3000);
}
Assign a variable to the interval and clear the interval based on the condition
this.interval = setInterval(() => {
client
.query({
query,
variables,
})
.then(res => {
if (res.status) {
console.log("FINISHED!");
clearInterval(this.interval)
}
});
}, 3000);
checkStatus() {
this.interval()
}

How do i prevent endless loop in while loop in action creator?

Trying to implement some kind of game loop, that will run until conditions are met.
However during testing I just can't solve the problem of while loop not waiting for resolve of promises, instead it just calls them over and over again causuing browser to crash.
The combatStart() is called when component is mounted
export const combatStart = () => {
return function (dispatch, getState) {
while (getState().mechanics.noOfEnemiesAttacked < 5) {
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 3000);
})
setTimeoutPromise.then((resp) => {
if(resp){
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
})
}
}
}
When i dispatch the action the "noOfEnemiesAttacked" increments, and when it reaches 5 the loop should stop. So it should last around 15 seconds.
The code works until I add the while loop, otherwise it works as expected, increments the value after 3 seconds when component is mounted.
How can I make this work?
Recursively doesnt work, it doesnt loop, just goes once:
export const combatStart = () => {
return function (dispatch, getState) {
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 2000);
})
setTimeoutPromise.then((resp) => {
if (resp) {
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
if (getState().mechanics.noOfEnemiesAttacked < 5) {
console.log(getState().mechanics.noOfEnemiesAttacked)
combatStart();
}
})
}
}
Wrapped it in a function, now it should work
export const combatStart = () => {
return function (dispatch, getState) {
function foo(){
let setTimeoutPromise = new Promise(resolve => {
let success = true;
setTimeout(function () { resolve(success) }, 2000);
})
setTimeoutPromise.then((resp) => {
if (resp) {
dispatch({
type: 'INCREMENT_ENEMIES_ATTACKED'
})
}
if (getState().mechanics.noOfEnemiesAttacked < 5) {
console.log(getState().mechanics.noOfEnemiesAttacked)
combatStart();
foo();
}
})
}
foo();
}
}

Categories