If-else condition with Realtime firebase - javascript

Is it possible to use if/else on firebase's realtime results? My database looks like this:
Previously I've tried it and it works if the result of both "waktu" is same, == recent.
but what I want is if one of the values "waktu" == recent, then "Hasil" = 0, if both of "time" nothing is equal to "Recent", then the value "Hasil" = 0.
if ("Recent" == (one of) "waktu") {
Hasil : "1";
} else {
Hasil : "0";
}
This is my code before, which value "Result" = 1, if both "waktu" values == recent. but i want if one values of "waktu" == Recent.
var recent = "";
var root = firebase.database().ref();
root.child("Time").on('value', (snapshot) => {
recent = snapshot.val().Recent;
});
root.child("jadwal-pakan").on('value', (snapshot) => {
snapshot.forEach(jadwal_waktu => {
if (jadwal_waktu.child("waktu").val() == recent) {
root.update({
Keadaan: {
Hasil: 1
}
});
} else {
root.update({
Keadaan: {
Hasil: 0
}
});
}
})
})
Thank you :)

The problem is in the timing of when the code executes. Since all data is loaded from Firebase asynchronously, your recent = snapshot.val().Recent may run after if (jadwal_waktu.child("waktu").val() == recent) { has run.
To ensure this is guaranteed, you'll need to nest the listeners like this:
root.child("Time").on('value', (snapshot) => {
recent = snapshot.val().Recent;
root.child("jadwal-pakan").on('value', (snapshot) => {
snapshot.forEach(jadwal_waktu => {
if (jadwal_waktu.child("waktu").val() == recent) {
root.update({
Keadaan: {
Hasil: 1
}
});
} else {
root.update({
Keadaan: {
Hasil: 0
}
});
}
})
})
});
Now there's no chance of the statements executing out of order, and the if (jadwal_waktu.child("waktu").val() == recent) { will work as expected.

Related

React Child Component Is Not Rerendering When Props Are Updated

My parent component takes input from a form and the state changes when the value goes out of focus via onBlur.
useEffect(() => {
let duplicate = false;
const findHierarchy = () => {
duplicationSearchParam
.filter(
(object, index) =>
index ===
duplicationSearchParam.findIndex(
(obj) => JSON.stringify(obj.name) === JSON.stringify(object.name)
)
)
.map((element) => {
DuplicateChecker(element.name).then((data) => {
if (data.status > 200) {
element.hierarchy = [];
} else {
element.hierarchy = data;
}
});
if (duplicate) {
} else {
duplicate = element?.hierarchy?.length !== 0;
}
});
return duplicate;
};
let dupe = findHierarchy();
if (dupe) {
setConfirmationProps({
retrievedData: formData,
duplicate: true,
responseHierarchy: [...duplicationSearchParam],
});
} else {
setConfirmationProps({
retrievedData: formData,
duplicate: false,
responseHierarchy: [],
});
}
}, [duplicationSearchParam]);
I have a child component also uses a useeffect hook to check for any state changes of the confirmationProps prop.
the issue is that the event gets triggered onblur, and if the user clicks on the next button. this function gets processes
const next = (data) => {
if (inProgress === true) {
return;
}
inProgress = true;
let countryLabels = [];
formData.addresses?.map((address) => {
fetch(`/api/ref/country/${address?.country}`)
.then((data) => {
countryLabels.push(data.label);
return countryLabels;
})
.then((countries) => {
let clean = MapCleanse(data, countries);
fetch("/api/v1/organization/cleanse", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(clean),
})
.then((data) => {
if (data.status > 200) {
console.log(data.message);
message.error(getErrorCode(data.message.toString()));
} else {
Promise.all([confirmationProps, duplicationSearchParam]).then(
(values) => {
console.log(values);
console.log(data);
setCleansed(data);
**setCurrent(current + 1);**
inProgress = false;
}
);
}
})
.catch((err) => {
console.log(err);
inProgress = false;
});
})
.catch((err) => {
console.log(err);
inProgress = false;
});
});
console.log(confirmationProps);
};
The important part in the above code snippet is the setCurrent(current + 1) as this is what directs our code to render the child component
in the child component, i have a use effect hook that is watching [props.duplicateData.responseHierarchy]
I do output the values of props.duplicateData.responsehierarchy to the console to see if the updated information gets passed to the child component and it does. the values are present.
I have a conditional render statement that looks like this
{cleansedTree?.length > 0 || treeDuplicate ? (...)}
so although the data is present and is processed and massaged in the child component. it still will not re render or display properly. unless the user goes back to the previous screen and proceeds to the next screen again... which forces a re-render of the child component.
I have boiled it down and am assuming that the conditional rendering of the HTML is to blame. Or maybe when the promise resolves and the state gets set for the confirmation props that the data somehow gets lost or the useefect doesn't pick it up.
I have tried the useefect dependency array to contain the props object itself and other properties that arent directly related
UPDATE: this is a code snippet of the processing that gets done in the childs useeffect
useEffect(() => {
console.log(props.duplicate);
console.log(props.duplicateData);
console.log(props.confirmationProps);
let newArray = props.duplicateData.filter((value) => value);
let duplicateCheck = newArray.map((checker) =>
checker?.hierarchy?.find((Qstring) =>
Qstring?.highlightedId?.includes(UUIDToString(props?.rawEdit?.id))
)
);
duplicateCheck = duplicateCheck.filter((value) => value);
console.log(newArray, "new array");
console.log(duplicateCheck, "duplicate check");
if (newArray?.length > 0 && duplicateCheck?.length === 0) {
let list = [];
newArray.map((dupeData) => {
if (dupeData !== []) {
let clean = dupeData.hierarchy?.filter(
(hierarchy) => !hierarchy.queryString
);
let queryParam = dupeData.hierarchy?.filter(
(hierarchy) => hierarchy.queryString
);
setSelectedKeys([queryParam?.[0]?.highlightedId]);
let treeNode = {};
if (clean?.length > 0) {
console.log("clean", clean);
Object.keys(clean).map(function (key) {
treeNode = buildDuplicate(clean[key]);
list.push(treeNode);
return list;
});
setCleansedTree([...list]);
setTreeDuplicate(true);
} else {
setTreeDuplicate(false);
}
}
});
}
}, [props.duplicateData.responseHierarchy]);
This is a decently complex bit of code to noodle through, but you did say that **setCurrent(current + 1);** is quite important. This pattern isn't effectively handling state the way you think it is...
setCurrent(prevCurrent => prevCurrent + 1)
if you did this
(count === 3)
setCount(count + 1) 4
setCount(count + 1) 4
setCount(count + 1) 4
You'd think you'd be manipulating count 3 times, but you wouldn't.
Not saying this is your answer, but this is a quick test to see if anything changes.
The issue with this problem was that the state was getting set before the promise was resolved. to solve this issue I added a promise.all function inside of my map and then proceeded to set the state.
What was confusing me was that in the console it was displaying the data as it should. but in fact, as I learned, the console isn't as reliable as you think. if someone runs into a similar issue make sure to console the object by getting the keys. this will return the true state of the object, and solve a lot of headache

If/else condition with Realtime firebase value

I wanted to ask, is it possible to use if/else on firebae's realtime results, which is:
enter image description here
if (Recent === waktu) {
Hasil : "1";
} else {
Hasil : "0";
}
This is my failed code:
// Eksekusi Jadwal
var waktu_jadwal = firebase.database().ref();
return waktu_jadwal.on('value').then((snapshot)=>{
return snapshot.forEach(jadwal_waktu=>{
if (jadwal_waktu.child("waktu").val() === (jadwal_waktu.child("Recent").val()) {
waktu_jadwal.update ({
Keadaan: {
Hasil: 1
}
});
} else {
waktu_jadwal.update ({
Keadaan: {
Hasil: 0
}
});
}
return console.log("added");
})
})
You can use an if/else as you have, as this is a callback function and will run like any other part of your script. Just be aware that you are using .on() which is an active firebase listener, if you intend on getting the value once, there is .once().
I would be cautious of shadowing variable names
try a more relative name such as 'Key'
return snapshot.forEach(Key=>{
if (Key.child("waktu").val() === (Key.child("Recent").val()) {
waktu_jadwal.update ({
You can also convert the object from snapshot data to a son object with
const data = snapshot.toJSON();

Change value of variable and check whether the value have changed

I want to check whether the text element changes on x seconds and apply the for loop and conditional structure to verify if the change is applied. If the text is still not changed it will refresh the page and check again
Cypress.Commands.add('checkApprovedStatus', (targetData) =>{
cy.get('div[class^=ui-table-scrollable-body]').contains('tr', targetData).first().parent().within(function(){
cy.get('td').eq(10).children('span[class^=customer-badge]').then(($status) =>
{
//let currStatus = $status.text()
//cy.log(currStatus)
for(let count = 0; count <= 5; count++)
{
let currStatus = $status.text()
cy.log(currStatus)
if (currStatus === 'approved')
{
//if (currStatus.contains('Approved', {matchCase:false}))
//{
cy.log("End to end testing completed. All checks have passed!!")
break
//}
}
else
{
cy.reload()
cy.wait(5000)
$status.trigger('change')
}
}
})
})
})
For loops generally crash and burn in Cypress, but you can use a recursive function to simulate the loop.
When the loop (reload/trigger change) fails to find the status, throw an error to fail the test, or just return.
const checkApprovedStatus = (targetData, attempt = 0) => {
if (attempt === 5) {
// used up all attempts, can either fail the test
throw 'Was never approved'
// or just return without failing
return
}
cy.get('div[class^=ui-table-scrollable-body]')
.contains('tr', targetData).first().parent()
.within(() => {
cy.get('td').eq(10).children('span[class^=customer-badge]')
.then($status => {
if ($status.text() === 'approved') {
cy.log("All checks have passed!!")
} else {
cy.reload()
cy.wait(5000)
$status.trigger('change')
checkApprovedStatus(targetData, ++attempt)
}
})
})
})

How to run multiple conditionals in an RXJS subcription

I am getting data back from a modal, I need to check the result and determine which outside function to fire based on many conditions.
I've verified that the data being passed back is formatted correctly and the series of else if's should be getting triggered, but it looks like it will skip over all conditions and do nothing.
What is the most productive way to go about implementing this logic?
My code:
dialogRef.afterClosed().subscribe(result => {
console.log('RESULT: ', result.delete);
if (result.isNew && !result.cancel) {
console.log('new story!');
this.boardService.updateTasks(this.job.id, [
...this.job.tasks,
result.task
]);
this.closeStories('update', this.job)
}
// means a delete has occured
else if (result.delete) {
this.closeStories('deleted triggered...')
// last story has been deleted, prompt newStory
if (this.stories.length < 2 && result === {}) {
console.log('Last story was deleted!');
this.closeStories('delete')
}
// a delete has happened
else if (this.stories.length > 1 && result === {}) {
console.log('A story was deleted!');
this.closeStories('deletedLast')
}
}
// means an update has occured
else if (result.id && !result.isNew) {
console.log('A story was Updated!');
const update = this.stories;
update.splice(result.index, 1, result.task);
this.boardService.updateTasks(this.job.id, update);
this.closeStories('update', this.job)
}
else if (result === undefined) {
return 0
}
// this.closedStoryListEmitter.emit(this.job);
console.log('hit close list event emitter!!');
});
//Have you checked other callbacks
dialogRef.afterClosed().subscribe(
result => {
console.log('RESULT: ', result.delete); //does this console.log executes?
//rest of the code
},
error=>{
//do something with and error
},
()=>{
//finished
}
);
I think if you want your if statements to be triggered, just do multiple if statements block without the else if block or at least that's how would I approach it.
...
if (result.isNew && !result.cancel) {
console.log('new story!');
this.boardService.updateTasks(this.job.id, [
...this.job.tasks,
result.task
]);
this.closeStories('update', this.job)
}
if (result.delete) {
this.closeStories('deleted triggered...')
// last story has been deleted, prompt newStory
if (this.stories.length < 2 && result === {}) {
console.log('Last story was deleted!');
this.closeStories('delete')
}
// a delete has happened
else if (this.stories.length > 1 && result === {}) {
console.log('A story was deleted!');
this.closeStories('deletedLast')
}
}
if (result.id && !result.isNew) {
console.log('A story was Updated!');
const update = this.stories;
update.splice(result.index, 1, result.task);
this.boardService.updateTasks(this.job.id, update);
this.closeStories('update', this.job)
}
if (result === undefined) {
return 0
}
...

How to make sync call in forEach loop Angular 6

I am trying to check my all 4 images is uploaded to server without any error, then redirect to another page so i am trying to perform some sync checking in my code (I have total 4 images in my imgResultAfterCompress array). below is my code:
if(Boolean(this.updateImage(data.AddId))===true)
{
this.router.navigate(['/job-in-hotels-india-abroad']);
}
updateImage(AddId:number):Observable<boolean>
{
this.cnt=0;
this.uploadingMsg='Uploading Images...';
this.imgResultAfterCompress.forEach( (value, key) => {
if(value!=='')
{
this.itemService.updateImage(this.employer.ID,AddId,key,value).subscribe(data=>{
if(data && data.status == 'success') {
this.uploadingMsg=this.uploadingMsg+'<br>Image No - '+(key+1)+' Uploaded.';
this.cnt++;
}
else
this.alertService.error(data.message);
});
}
if(this.cnt==4)
this.uploadingDone= true;
else
this.uploadingDone= false
});
return this.uploadingDone;
}
Every time i am getting cnt value is 0, i want its value = 4 (completely uploaded all images) then redirection will occurred.
The easier way is to wrap your observables into a single one, using zip operator
https://rxjs-dev.firebaseapp.com/api/index/function/zip
Thus once every request is finished successfully your zipped Observable will be fulfilled.
UPDATE:
This is how I think it should look like. I could miss something specific, but the global idea should be clear
redirect() {
this.updateImages(data.AddId).subscribe(
() => this.router.navigate(['/job-in-hotels-india-abroad']),
error => this.alertService.error(error.message)
)
}
updateImages(AddId: number): Observable<boolean[]> {
this.uploadingMsg = 'Uploading Images...';
const requests: Observable<boolean>[] = [];
this.imgResultAfterCompress.forEach((value, key) => {
if (!value) {
return;
}
requests.push(
this.itemService.updateImage(this.employer.ID, AddId, key, value)
.pipe(
tap(() => this.uploadingMsg = this.uploadingMsg + '<br>Image No - ' + (key + 1) + ' Uploaded.'),
switchMap((data) => {
if (data && data.status == 'success') {
return of(true)
} else {
throwError(new Error('Failed to upload image'));
}
})
)
)
});
return zip(...requests);
}
Finally got the desire result by using forkJoin
Service.ts:
public requestDataFromMultipleSources(EmpId: number,AddId:number,myFiles:any): Observable<any[]> {
let response: any[] = [];
myFile.forEach(( value, key ) => {
response.push(this.http.post<any>(this.baseUrl + 'furniture.php', {EmpId: EmpId, AddId:AddId,ImgIndex:key,option: 'updateAdImg', myFile:value}));
});
// Observable.forkJoin (RxJS 5) changes to just forkJoin() in RxJS 6
return forkJoin(response);
}
my.component.ts
let resCnt=0;
this.itemService.requestDataFromMultipleSources(this.employer.ID,AddId,this.imgResultAfterCompress).subscribe(responseList => {
responseList.forEach( value => {
if(value.status=='success')
{
resCnt++;
this.uploadingMsg=this.uploadingMsg+'<br>Image No - '+(value.ImgIndex+1)+' Uploaded.';
}
else
this.uploadingMsg=this.uploadingMsg+'<br>Problem In Uploading Image No - '+(value.ImgIndex+1)+', Please choose another one.';
});
if(resCnt === this.imgResultAfterCompress.length)
{
this.alertService.success('Add Posted Successfully');
this.router.navigate(['/job-in-hotels-india-abroad']);
}
else
this.alertService.error('Problem In Uploading Your Images');
});
You shouldn't try to make sync call within a loop. It is possible using async/await, but it's bad for app performance, and it is a common anti-pattern.
Look into Promise.all(). You could wrap each call into promise and redirect when all promises are resolved.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Categories