Getting the initial state after unchecked checkbox input with React - javascript

I am building a filter section where I am fetching data through my API and setting up a new state ‘[result]’. The process is simple since data are fetched on click event and with certain condition. Data are stocked in an array since the user is able to filter several input checked.
My goal is to remove a particular index when I unchecked a checkbox input and if array is empty then reset my state to the data it fetched when the page first loaded.
I heard lodash could help me building my feature though I don't know how to implement on my react-app.
How could I build this process ?
Here’s my code :
handleFilterButtons = event => {
var filterIcons = event.target.getAttribute("name");
var valueInput = event.target.value;
var apiFilters = `https://backend.greatsaigon.com/api/v1/en/directories/${
this.state.directory
}/venues`;
axios
.get(apiFilters)
.then(response => {
let result;
let prevResult = [];
let toggleButton;
response.data.forEach(req => {
if (filterIcons === "Hair") {
if (req.options.beauty.hair.treatment !== "0") {
req.options.beauty.hair.treatment.forEach(res => {
if (res === valueInput && toggleButton !== undefined) {
result = req;
this.state.stockResult.unshift(result);
}
});
}
} else if (filterIcons === "Nails") {
if (req.options.beauty.nails.treatment !== "0") {
req.options.beauty.nails.treatment.forEach(res => {
if (res === valueInput) {
result = req;
this.state.stockResult.unshift(result);
}
});
}
} else if (filterIcons === "Spa & Massage") {
if (req.options.beauty.spa.treatment !== "0") {
req.options.beauty.spa.treatment.forEach(res => {
if (res === valueInput) {
result = req;
this.state.stockResult.unshift(result);
}
});
}
}
});
this.setState({
result: _.uniq(this.state.stockResult),
isToggle: toggleButton
});
})
.catch(function(error) {
console.log(error);
});
};

Related

Nuxt failed Vue hydrate "Attempting to hydrate existing markup but container is empty. Performing full mount instead."

I'm trying to implement SSR in my project, but constantly getting this error/warn.
How can I know what is wrong with my code?
I have a lot of components in my project, dont know if I need to show you all of my code, but there is main TypeScript
import {Book} from '#/data/data'
const useBooksStore = () => {
const books = useState<Book[]>('books', () => [])
const savedBooks = useState<String[]>('savedBooks', () => [])
const isLoading = useState('isLoading', () => false)
const apiKey = 'AIzaSyBz-gCuGyQopm_Ey2QWPrMGghy0D0e1FYY'
const booksCookie = useCookie('savedBooks')
//loading the list of books on query
async function loadBooks(query: string) {
const response = await fetch(`https://www.googleapis.com/books/v1/volumes?q=${query}&key=${apiKey}`)
if (response.ok) {
const result = await response.json()
if (result.items) {
books.value = books.value.filter(book => book.favourites === true)
result.items.forEach(item => {
const existingBook = books.value.find(book => book.id === item.id)
if (!existingBook) {
let data = constructBookData(item)
books.value.unshift(data)
}
})
} else {
books.value = books.value.filter(book => book.favourites === true)
throw new Error('Not Found')
}
}
}
//loading saved books from cookies
async function loadSavedBooks() {
if (booksCookie.value) {
savedBooks.value = booksCookie.value
}
let response, result
for (const savedBook of savedBooks.value) {
const existingBook = books.value.find(book => book.id === savedBook)
if (!existingBook) {
response = await fetch(`https://www.googleapis.com/books/v1/volumes/${savedBook}?key=${apiKey}`)
if (response.ok) {
result = await response.json()
if (!books.value.find(book => book.id === result.id)) {
let data = constructBookData(result)
data.favourites = true
books.value.push(data)
}
}
} else {
existingBook.favourites = true
}
}
}
//returns a new book object
function constructBookData(result): Book {
const data = {
id: result.id,
title: String(result.volumeInfo.title),
imgUrl: result.volumeInfo.imageLinks && result.volumeInfo.imageLinks.thumbnail,
shortDescr: result.volumeInfo.description,
price: result.saleInfo.saleability === "FOR_SALE" ? Math.floor(result.saleInfo.retailPrice.amount) : result.saleInfo.saleability.split('_').join(' '),
infoLink: result.volumeInfo.infoLink,
favourites: false
}
return data
}
//handling loading (needed for loading spinner to show)
async function handleLoading(callback) {
isLoading.value = true
try {
await callback()
} catch (err) {
throw err
} finally {
isLoading.value = false
}
}
//toggle favourite status of a book card
function toggleFavourite(bookId: string) {
const book = books.value.find(book => book.id === bookId)
book.favourites = !book.favourites
if (book.favourites && !savedBooks.value.find(book => book === bookId)) {
savedBooks.value.push(book.id)
} else {
savedBooks.value.splice(savedBooks.value.findIndex(book => book === bookId), 1)
}
booksCookie.value = JSON.stringify(savedBooks.value)
}
//returns a list of saved books
function getSavedBooks() {
if (books.value) {
return books.value.filter(book => book.favourites === true)
}
}
//returns loading status
function getLoading() {
return isLoading.value
}
return {
books,
loadBooks,
getSavedBooks,
toggleFavourite,
loadSavedBooks,
handleLoading,
getLoading
}
}
export default useBooksStore
My main question is how can I know whats wrong with my code to solve this problem?
I found an answer. The issue was in this code
<component :is="type === 'link' ? 'a' :
(type === 'button' && 'button')" :href='href' class="btn" #click="emit('click')" :class="class">
<slot/>
</component>
So I think dont use this type of component rendering, because it is not SSR friendly a guess) I rewrite it to this code
<a v-if="type === 'link'" :href="href" class="btn" #click="emit('click')">
<slot/>
</a>
<button v-else-if="type === 'button'" :href="href" class="btn" #click="emit('click')">
<slot/>
</button>

How to call a function after subscriber complete in angular 8+

Hello everyone I am learning angular and firebase. So the idea is I fetch some ticket from my ticket collection and after fetching add some new property in it but the problem is when I receive half data my ordering function call (the function which is responsible for adding a property). or in simple word we can say I receive data in stream form.
get_ticket() {
console.log('have permission');
this.get_ticket_service
.get_ticket_company(this.user.company)
.subscribe((res) => {
console.log('get response');
this.unStructure_ticket = res.map((e) => {
return {
id: e.payload.doc.id,
item: e.payload.doc.data(),
};
});
this.odering_ticket(this.unStructure_ticket)
});
ordering function
odering_ticket(data) {
const info = [];
console.log('hi');
data.map((ticket) => {
if (ticket.item.seen == false) {
ticket.item.ticketID = ticket.id;
ticket.item.ticketType = 'new';
info.push(ticket.item);
} else if (
ticket.item.new == true &&
ticket.item.currently_handle_sme_ID == undefined
) {
ticket.item.ticketID = ticket.id;
ticket.item.ticketType = 'not assigned';
info.push(ticket.item);
} else if (
ticket.item.currently_handle_sme_ID == localStorage.getItem('uid') &&
!this.has_view_all_ticket_permission
) {
ticket.item.ticketID = ticket.id;
ticket.item.ticketType = 'assigned';
info.push(ticket.item);
} else if (
ticket.item.currently_handle_sme_ID != undefined &&
this.has_view_all_ticket_permission
) {
ticket.item.ticketID = ticket.id;
ticket.item.ticketType = 'assigned';
info.push(ticket.item);
}
});
console.log('end map');
return info;
}
service.ts
get_ticket_company(company) {
return this.firebase_store
.collection('Ticket', (ref) => ref.where('company', '==', company))
.snapshotChanges();
}
output
have permission ,
get response ,
hi ,
end map ,
get response ,
hi ,
end map,
I want to call my ordering function one's after I receive all data
You must try to use the last RxJs operator which will make your pipeline wait until the last emitted value.
this.get_ticket_service
.get_ticket_company(this.user.company).pipe(
tap((poRes) => {
console.log('get response');
if (this.unStructure_ticket === undefined) {
// Initialize your data structure.
this.unStructure_ticket = res.map((e) => {
return {
id: e.payload.doc.id,
item: e.payload.doc.data(),
};
});
} else {
// Add or concate the data received
// this.unStructure_ticket.push()//;
}
}),
last(), // Wait for the last emitted value.
tap((poRes) => {
this.odering_ticket(this.unStructure_ticket);
}),
).subscribe();
Example of how this should work, but not tested code.

multiple http.post in Angular

I am trying to send an http.post request for each element of an array, my method works well, but when I subscribe, it does it for each of the requests, if someone could help me optimize this, I will I would really appreciate it, here I leave the snippets of my code.
component.ts
saveExclusion() {
this.indForm.value.Centers.forEach(element => {
for (const days of this.exclusionDays) {
delete days.horadesde;
delete days.horahasta;
delete days.id;
for (const key in days) {
if (days[key] === true) {
days[key] = true;
}else if (days[key] === false) {
delete days[key];
}
}
}
const valueForm = this.indForm.value;
valueForm.ResourceId = this.idResource;
valueForm.TimeZoneId = 'America/Santiago';
valueForm.CenterId = element;
this.exclusionFunc = false;
this.apiFca.saveNew(valueForm, this.exclusionDays)
.pipe(last()).subscribe((res: any) => {
console.log(res)
if (res === '200') {
this.successMessage = true;
this.exclusionDays = [];
this.indForm.reset();
this.ngOnInit();
setTimeout(() => {
this.successMessage = false;
}, 3000);
}
}, err => {
console.log('error', err);
});
});
}
service.ts
saveNew(exclusionData, daysBlock) {
let reason = '';
const dt = new Date();
const n = dt.getTimezoneOffset();
const tz = new Date(n * 1000).toISOString().substr(14, 5);
if (exclusionData.OtherReason) {
reason = exclusionData.ExclusionReason + ' ' + exclusionData.OtherReason;
} else {
reason = exclusionData.ExclusionReason;
}
if (exclusionData.ExclusionType !== 'Partial' ) {
daysBlock = [];
}
const data = {Exclusion: new ExclusionClass(
[],
reason,
exclusionData.ExclusionType,
exclusionData.Repetition,
exclusionData.CenterId,
exclusionData.ProfessionalName,
exclusionData.ResourceId,
daysBlock,
exclusionData.TimeZoneId,
'Exclude',
exclusionData.Unit,
exclusionData.ValidFrom + 'T' + exclusionData.ValidTimeFrom + ':00-' + tz,
exclusionData.ValidTo + 'T' + exclusionData.ValidTimeUntil + ':59.999-' + tz
)};
if (exclusionData.CenterId === '') {
delete data.Exclusion.CenterId;
}
return this.http
.post("url", data)
.pipe(
map((res: any) => {
return res.code;
})
);
}
greetings, and I look forward to your comments, thanks.
I'm not fully confident in my rxjs knowledge but it looks like, because of .pipe(last()), you are only watching the last request? I'd recommend you only set success if all completed without error, like
this.apiFca.saveNew(valueForm, this.exclusionDelays)
.subscribe(
res => {
console.log(res);
},
err => {
console.log(err);
},
() => {
this.successMessage = true;
// etc. etc. etc.
});
or maybe instead of using this.successMessage use something like this.saveState$ that would be the a BehaviorSubject object initialized with 'idle' (or some enum thereof) that your saveExclusion() function manages. That way, the beginning of your saveExclusion() function could
set const saveState$ = this.saveState$
assert that saveState$.getValue() === 'in process' or if not, do something about it,
saveState$.next('in process');
and you could change your subscribe line to
this.apiFca.saveNew(valueForm, this.exclusionDelays)
.subscribe(
res => {
if (res !== '200') {
saveState$.next('unexpected result')
} },
err => {
console.log(err);
saveState$.next('error');
},
() => {
if (saveState$.getValue() === 'in process') {
saveState$.next('success');
} }
);
And then you can subscribe to your component's saveState$ as well (though outside of the component you'd want to provide saveState$.asObservable() so values can't be injected by outside code). This affords some elegant event-driven code in your component initialization:
saveState$.pipe(filter(val => val === 'error'))
.subscribe(functionToTellYourUserThereWasAnError);
// if successful, we want other code to know, but immediately change it back to 'idle' even if other code errors
saveState$.pipe(filter(val => val === 'success')
.subscribe(val => saveState$.next('idle'));
// upon success, reset me
saveState$.pipe(filter(val => val === 'success'))
.subscribe(
val => {
this.exclusionDays = [];
// etc. etc.
// setTimeout not needed because set to 'idle' in a different thread.
}
)
Plus, I think your template could reflect and change the UI in response to changes in saveState$ as well, so your save button can be enabled/disabled based on whether or not saveState is 'idle', etc.

How to Apply Month Filter To Table React

Below is My code I am using dropdown and values, for example, clicking on January the 1 value is sent to function and states updates and that month record is shown but after that when I will try to see another month's data then it not showing. and when click on default I want to all data as it was previously.
Thanks In Advance!
this.setState((prevState) => {
if (mon !== null || mon !== 0 || mon !== undefined) {
const rows = prevState.rows.filter((element) => {
return element.monthname === mon;
});
return {
rows,
};
} else {
const rows = prevState.rows.filter((element) => {
return element.monthname !== null;
});
return {
rows,
};
}
});
don't use prevState :
keep rowsOriginal in the state alongside the rows :
this.state = {
rows:[]
rowsOriginal:[]
}
componentDidMount(){
fetchRows().then(rows=>this.setState({rows:rows,rowsOriginal:rows})
}
then always filter from rowsOriginal and set status to rows:
this.setState({rows:rowsOriginal.filter((element) => {
return element.monthname === mon;
})})
When setting default:
this.setState({rows:rowsOriginal})
So,
if (mon !== null && mon !== 0 && mon !== undefined) {
this.setState({rows:rowsOriginal.filter((element) => {
return element.monthname === mon;
})})
}
else {
this.setState({rows:rowsOriginal})
}
Here you go with a solution
this.state = { filteredRow: [] }
this.setState((prevState) => {
if (mon) {
const filteredRow = prevState.rows.filter((element) => {
return element.monthname === mon;
});
return {
filteredRow
};
} else {
return {
filteredRow: prevState.rows
};
}
});
Use a separate state varaible to maintain your filtered rows.
Else condition filter is not required as you can directly show all the records. Filter will unnecessary increase the compute by looping through data.

Alert Controller stacked in nested condition

I am doing a comparison to validate QR Code using the data retrieved from Firestore. It should navigate to another page if the condition is satisfied. Based on my code, it kept on returning 'Invalid Code' and multiple stacked alerts even if the condition is true. Is there a simpler solution to compare? I just can't quite figure it out. Here's my code.
scan() {
this.scanner.scan().then((data) => {
let qrcode = data.text.length;
this.afs.firestore.collection('item1')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc1 => {
var data1 = doc1.data();
var itemName = data1.itemname;
var itemID = data1.itemid;
this.afs.firestore.collection('item2')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc2 => {
var data2 = doc2.data();
var itemName2 = data2.itemname2;
var itemID2 = data2.itemid2;
var description = data2.description;
if (doc1.exists) {
if (qrcode == 10 && itemName == itemName2 && itemID == itemID2) {
this.navCtrl.navigateForward('/nextPage');
} else {
return this.presentAlert('Error', 'Invalid Code')
}
} else if (description == null) {
return this.presentAlert('Error', 'Nothing found')
} else {
return this.presentAlert('Error', 'QR Not Found')
}
})
})
})
})
}, (err) => {
console.log('Error: ', err);
})
}
I think that your issue is because you have 2 nested "forEach" cycles and even is you routine has a valid condition there isn't a return statement and your cycles never been stopped(using break)
I adjusted your code to break the cycles
scan() {
this.scanner.scan().then((data) => {
let qrcode = data.text.length;
this.afs.firestore.collection('item1')
.get()
.then((snapshot) => {
snapshot.docs.forEach(doc1 => {
var data1 = doc1.data();
var itemName = data1.itemname;
var itemID = data1.itemid;
var check = this.afs.firestore.collection('item2')
. get()
.then((snapshot) => {
snapshot.docs.forEach(doc2 => {
var data2 = doc2.data();
var itemName2 = data2.itemname2;
var itemID2 = data2.itemid2;
var description = data2.description;
if (doc1.exists) {
if (qrcode == 10 && itemName == itemName2 && itemID == itemID2) {
return true
} else {
return this.presentAlert('Error', 'Invalid Code')
}
} else if (description == null) {
return this.presentAlert('Error', 'Nothing found')
} else {
return this.presentAlert('Error', 'QR Not Found')
}
})
})
if (check){
this.navCtrl.navigateForward('/nextPage');
break
}else{
return check
}
})
})
}, (err) => {
console.log('Error: ', err);
})
}

Categories

Resources