Caching api response using react-query when changing routes but be able to receive data when reloading the page - react-router-dom

I have prepared a simple demo with react-router-dom 6 and react query.
I have a couple of routes and a fetch call that takes place on the first route (Home).
What I want to achieve is navigating to the About page or any other page and do not perform another request for a certain time period (maybe never again) but if I refresh the page I want to be able to re trigger the request to get the data.
I have tried using staleTime when but if I refresh the page I get no results, just a blank page. refreshInterval works on refresh but does not keep the data when I change routes.
I have also tried this pattern in this article but still I don't get the job done.
Probably it may be that something I don't understand but the question is how do I avoid making the same request over and over again, perfrm it only once but still being able to get the data if I refresh the page when navigating between different routes.
Demo

The solution to the problem came from one of the maintainers on the official github repo eventually and is related to adding placeholderData as an empty array instead of initialData and setting staleTime to Infinity in my case as I only want to perform the request once.
Setting placeholderData gives you the opportunity to show some dummy data normally until you fetch the real but in my case it seems to do the job. More to read regarding this at this source
const { isFetching, data: catImages } = useQuery({
queryKey: ["catImages"],
queryFn: getCatImages,
placeholderData: [],
staleTime: Infinity
});

Related

Angular/NodeJS - Mongoose Pagination

This is more a design question than a lot of code.
I have my angular client query a mongodb collection via http and nodejs backend.
I want to paginate the result, so what I do is on the angular side, keep track of the page I'm on and the # of results I would like on each page, and I pass that on to my backend via an http call.
Then my backend has code that looks something like this:
schema.find({name: query, _userId: req.body._userId}).sort({ name: 'asc' }).limit(req.body.num_results).skip(req.body.page * req.body.num_results).then(response => {
Now I'd like to put "<" and ">" arrows on my client's html where every time left or right is clicked it traverses pages (via a new http call), but then make it so that "<" is disabled on page 0, and ">" is disabled on the last page of results. I've figured out how to disable the "<" - simply make the button go away when you're on page 0. But having trouble figuring out the best way to discover that I'm on the last page. One method could be for my backend to return the total number of results and then my front-end tracks where I am relative to the total #, but that involved another db call, move variables passed over http, more management on the front-end. Any ideas on how to implement a 'cleaner' solution?
Thank you.
You do not need to make any additional api call. You can return any additional information in the form of Http header when making api call. so, in this case return X-TOTAL-COUNT

ajaxProgressiveLoad="load", initialFilter and ajaxURLGenerator

Im using an ajaxProgressiveLoad="load" successfully, but intialFilter doesnt seem to get applied during the load, as all the rows are displayed. Also, the calculation for the last_page response from the server is quite expensive (and will get more so!) so I was trying to use ajaxURLGenerator to include a last_page=getPageMax() request parameter to tell my server that it has already calculated the last_page already, and just return this value. But getPageMax() returns false, as detailed in the docs to indicate that pagination is not being used.
So at the moment, I'm under the impression that these 2 features/functions are not available under progressiveLoad ? If not, is there another way around to do this ?
Thanks
If you are using progressive loading then i would suggest that you use ajaxFiltering option to pass the filter information back to the server and filter it server side to reduce the amount of data sent in the request.
ajaxFiltering=true
The getPageMax function is only available when pagination is being used explicitly, not when progressive loading is being used
Importantly the last_page value is primarily used in this instance to let Tabulator know that there are still more pages to load, you could effectively always return this value as 1 or 2 above the current page while there is still information available and set it to the current page when you have reached the last set of records, that way it should continue to try and load data without the overhead of the final page calculation.

NodeJS Express pagination with Google Datastore how to integrate cursor queries with UI control

I am stuck on implementing Pagination and I just need a bit of help, either some example code or even just a hint to help me proceed in the right direction.
I'm looking for some guidance on how to integrate Google Datastore database cursors with front-end UI pagination controls. I know how to build an angular pagination service, but that's with retrieving all the data at once and due to performance issues (5,000 records+) I want to use cursors to retrieve data in subsets.
NOTE: There's a similar question here, but I need more detail than this accepted answer provides. Node pagination in google datastore
QUESTION: How can I integrate the paginated datastore cursor queries with the front-end UI controls to allow the user to select the current page and control number of results displayed on each page?
I need to build a page that displays a large number of records with dynamic pagination. The user must be able to select the number of records display on each page.
Since there are several thousand records that might be returned at one time, I want to use cursors to retrieve subsets of data.
There is an example of how to paginate in the docs, but it is a pretty basic example and does not demonstrate how to integrate with front-end UI controls.
Can anyone provide a more detailed example and/or point me in the right direction on where to begin with this requirement? Unfortunately I haven't been able to find any detailed examples online.
https://googlecloudplatform.github.io/google-cloud-node/#/docs/datastore/1.1.0/datastore
Paginating Records
var express = require('express');
var app = express();
var NUM_RESULTS_PER_PAGE = 15;
app.get('/contacts', function(req, res) {
var query = datastore.createQuery('Contacts')
.limit(NUM_RESULTS_PER_PAGE);
if (req.query.nextPageCursor) {
query.start(req.query.nextPageCursor);
}
datastore.runQuery(query, function(err, entities, info) {
if (err) {
// Error handling omitted.
return;
}
// Respond to the front end with the contacts and the cursoring token
// from the query we just ran.
var frontEndResponse = {
contacts: entities
};
// Check if more results may exist.
if (info.moreResults !== datastore.NO_MORE_RESULTS) {
frontEndResponse.nextPageCursor = info.endCursor;
}
res.render('contacts', frontEndResponse);
});
});
One thing to keep in mind is the first item on the Limitations of cursors list:
A cursor can be used only by the same project that performed the original query, and only to continue the same query. It is not
possible to retrieve results using a cursor without setting up the
same query from which it was originally generated.
So you need to always be able to re-create the original query inside your handler, which means you need to pass around the equivalent of your NUM_RESULTS_PER_PAGE value from one request to another. You also need to reset the query every time that value changes - meaning you can't continue browsing from where you were after changing the number of results displayed per page.
Then, to be able to use the pagination, you also need to pass around the current cursor value from one request to another, updated at every request.
Now I'm not a NodeJS user, so I can tell exactly how this passing values around from one request to another would typically be implemented. In your code req.query.nextPageCursor and frontEndResponse.nextPageCursor appear to be intended for this, but I can't tell if that's OK or not. Maybe this is a less specific question easier to find an answer for.
In python webapp2, for example, I can store such values server-side in the user's session in one request and read them from the session in a subsequent request. Donno if this is of any help.

How to do not reset search results in Yii zii.widgets.grid.cgridview

I have zii.widgets.grid.cgridview on admin page, and when I search some records and visit view one of them, and after return to admin page results is reseted. May I save them someway?
As a suggestion:
First disable Ajax update in your CGridView's view:
'ajaxUpdate' => false
Now, it sends data via GET request. If you save the current GET, it would be possible to use the result later. It is accessible with:
$_GET['YOUR_MODEL_NAME'];
If you want to use it in somewhere else, you can get values from GET and put it into a CDBCriteria.
Others might offer another way.

Combine multiple http request or not?

Some web design questions.
Combine POST with GET?
When user clicks a button, I need to send one POST to submit a form, then need to GET a json object to replace some DOM fields. Should I combine them into one request so save one round trip time?
Multiple GET json request?
When user clicks a button, I need to GET 3 or 4 json object. Should I send 3 or 4 GET request, or just one and combine the json into one large json at back-end?
So basically, I'm not sure which is heavier: round trip time VS a little complexed back-end and front-end logic.
Any comment is welcome!
if i understood your question right...you have a dependency on your get requests...that is to say the second get depends on the first...if that is the case, obviously you need to take consecutive get operations...however, if that is not the case that is if you know the order of get request and the response won't be affected by local conditions...then i suggest you do post/get operations on server side...trigger the first one an let the server handle the rest and get the result...
of course you would not want users do multiple get requests for one simple operation...

Resources