Reputation: 418
I am creating NgRx application but I am quite confused about its implementation as it is my first app with NgRx. I have a store with "Companies" state. I gotta search the companies and return if found. If the required company is not found it should call the API and fetch the results likewise but the process is circular and runs infinite time.
Here is my code:
this.companySearchCtrl.valueChanges
.pipe(
debounceTime(300),
distinctUntilChanged()
)
.subscribe(val => {
if (val !== ' ' || val !== '') {
this.store.select(getCompanys).subscribe(data => {
console.log(data);
//filter companies on the basis of search text
const filteredData = data.filter(x =>
x['name']
.toLowerCase()
.startsWith(this.companySearchCtrl.value.toLowerCase())
);
console.log(filteredData);
if (filteredData.length === 0) { //if data is not found in store
console.log('got a call');
this.store.dispatch(
new CompanyActions.find({
where: { name: { regexp: `${val}/i` } } // call to API to search with regExp
})
);
} else {
// if required data found in store
console.log('got no call');
this.filteredCompanies$ = of(filteredData);
}
});
}
});
This process runs fine if data is found in store. If data is not found in store or I dont get any results from API call it runs infinitely. How can I make this correct?
Upvotes: 5
Views: 3693
Reputation: 15271
Make a few conventions:
state.Companies = null
is initial state if no request to server has been sent yetstate.Companies = []
is state after first request was sent but no companies returned from servercreateSelector
that filters your companies based on criteria you needwithLatestFrom
in your effects which will enable you to check store state within effectsNow, turn the logic the other way around:
state.Companies
is null
or notnull
> fire api requeststate.Companies
was not null
that means either you need to refresh your Companies
collection or the value doesn't exist on serverUpvotes: 5
Reputation: 29
Create another action named dataNotFound
. If you found data then set its state isFound
to true and if data does not find, set its state isFound
to false and always before sending call with regex check isFound
that either data was found in previous call or not. If data was not found then don't send call again.
I've made a little bit change in your code to manage this. You just have to create an action dataNotFound
now.
this.companySearchCtrl.valueChanges
.pipe(
debounceTime(300),
distinctUntilChanged()
)
.subscribe(val => {
if (val !== ' ' || val !== '') {
this.store.select(getCompanys).subscribe(data => {
console.log(data);
//filter companies on the basis of search text
const filteredData = data.filter(x =>
x['name']
.toLowerCase()
.startsWith(this.companySearchCtrl.value.toLowerCase())
);
console.log(filteredData);
if (filteredData.length === 0) { //if data is not found in store
console.log('got a call');
this.store.select(isDataFound).subscribe(isFound => {
if(isFound) {
this.store.dispatch(
new CompanyActions.find({
where: { name: { regexp: `${val}/i` } } // call to API to
search with regExp
})
);
} else {
this.store.dispatch(new CompanyActions.dataNotFound({isFound: false}));
}
});
} else {
// if required data found in store
console.log('got no call');
this.store.dispatch(new CompanyActions.dataNotFound({isFound: true}));
this.filteredCompanies$ = of(filteredData);
}
});
}
});
Upvotes: 3