React Query dynamic incremental queries - javascript

I am currently fetching data from a 3rd party api in a React application.
The way the api is structured, the flow goes like this:
// Get a list of data
response = GET /reviews
while response.data.nextPageUrl is not null
response = GET ${response.data.nextPageUrl}
I currently have this logic inside of a "fetch method"
const fetchMyData = () => {
// The logic above
}
const query = useQuery(['myKey'], () => fetchMyData, {...})
This works, but comes with some drawbacks.
There is no way to see the progress of the individual requests (to be used in a progress bar)
It cannot leverage React Query's caching functionality on an individual request.
For example: If there are 10 requests to be made, but during the 5th request the user refreshes the page, they will need to restart from the beginning.
I am aware of useQueries but since I do not know the query urls until I have received the first request I do not see how I could use it.
Is there a better approach or way to satisfy the 2 issues above?
Thank you in advance

What you need is Infinite Queries. useInfiniteQuery works similar to useQuery but it's made for fetching by chunks. useInfiniteQuery has extra parameters like getNextPageParam which you will use to tell React Query how to determine the next page. This hook also returns fetchNextPage, hasNextPage (among others), which will allow you to implement patterns like a "show more" button that appears for as long as there is a next page.
By using infinite queries you still leverage on React Query caching. Check the docs for more info.

Related

Refresh page automatically in react js

I have a react js application to show data using an Axios GET call. I want to update my data automatically by repeating the GET call, and not using a refresh button. I could add a timer to do this. I have only a post call from an external server to send on my react js app URL. Could you suggest me a workaround?
You can use setInterval() function in JavaScript to repeat the GET call after a specific interval.
Here you go -
useEffect(() => {
const interval = setInterval(() => {
axios.get(`your-url`)
.then(res => setData(res.data))
.catch(err => console.error(err));
}, 5000); //set your time here. repeat every 5 seconds
return () => clearInterval(interval);
}, []);
The way I see it, there are 3 options available to you.
Option 1: Would be to have WebSockets available in your API and connect your react app to them. Whenever the data is updated the app receives and "update" with the changes. This is the best option if you (or your team) are the devs for the backend/API.
Option 2: Having a button that redos your request would be the easy option. The user can always re-request whenever they want.
Option 3: Re-requesting from time-to-time can be achieved by using setInterval(). Which most people would not recommend unless 100% necessary. This method can be harmful for various reasons.
You're requesting multiple times, not sure if changes were made, wasting bandwidth and clogging your API with "useless" requests
If the API isn't yours, they can block your app from accessing due to multiple requests being made

Fastest redirects Javascript

My main function is I am creating a link-shortening app. When someone entered a long URL, it will give a short URL. If the user clicked on the short link it will search for the long URL on the DB and redirect it to the long URL.
Meantime I want to get the click count and clicked user's OS.
I am currently using current code :
app.get('/:shortUrl', async (req, res) => {
const shortUrl = await ShortUrl.findOne({short: req.params.shortUrl})
if (shortUrl == null) return res.sendStatus(404)
res.redirect(shortUrl.full)
})
findOne is finding the Long URL on the database using ShortID. I used mongoDB here
My questions are :
Are there multiple redirect methods in JS?
Is this method work if there is a high load?
Any other methods I can use to achieve the same result?
What other facts that matter on redirect time
What is 'No Redirection Tracking'?
This is a really long question, Thanks to those who invested their time in this.
Your code is ok, the only limitation is where you run it and mongodb.
I have created apps that are analytics tracker, handling billion rows per day.
I suggest you run your node code using AWS Beanstalk APP. It has low latency and scales on your needs.
And you need to put redis between your request and mongodb, you will call mongodb only if your data is not yet in redis. Mongodb has more read limitations than a straight redis instance.
Are there multiple redirect methods in JS?
First off, there are no redirect methods in Javascript. res.redirect() is a feature of the Express http framework that runs in nodejs. This is the only method built into Express, though all a redirect response consists of is a 3xx (often 302) http response status and setting the Location header to the redirect location. You can manually code that just as well as you can use res.redirect() in Express.
You can look at the res.redirect() code in Express here.
The main things it does are set the location header with this:
this.location(address)
And set the http status (which defaults to 302) with this:
this.statusCode = status;
Then, the rest of the code has to do with handling variable arguments, handling an older design for the API and sending a body in either plain text or html (neither of which is required).
Is this method work if there is a high load?
res.redirect() works just fine at a high load. The bottleneck in your code is probably this line of code:
const shortUrl = await ShortUrl.findOne({short: req.params.shortUrl})
And, how high a scale that goes to depends upon a whole bunch of things about your database, configuration, hardware, setup, etc... You should probably just test how many request/sec of this kind your current database can handle.
Any other methods I can use to achieve the same result?
Sure there are. But, you will have to use some data store to look up the shortUrl to find the long url and you will have to create a 302 response somehow. As said earlier, the scale you can achieve will depend entirely upon your database.
What other facts that matter on redirect time
This is pretty much covered above (hint, its all about the database).
What is 'No Redirection Tracking'?
You can read about it here on MDN.

How can I programmatically retreive the request timing metrics for api calls going from my app in browser

I basically want all the highlighted information for api calls going from my app after the app has been loaded.
I am aware that there are performance timing apis like https://developer.mozilla.org/en-US/docs/Web/API/Performance using which we get the above mentioned fileds but the issue is this api only give the network requests at/up to page load and cannot poll for subsequent async/ajax calls.
I am wondering if this is a limitation currently or if there exists some other api I can use to retrieve the above mentioned metrics.
Did you look at PerformanceObserver? It observes these performance measurement events and is notified of the new entries too.
You need to:
create an instance of the observer, and
let the observer know what type of entries you want to observe.
const observer = new PerformanceObserver(list => {
list.getEntries().forEach(doSomething);
});
observer.observe({ entryTypes: ["resource"] });
entrytypes is supposed to be an array of the PerformanceEntry.entryType. resource is what you pass for resources.

Firebase: best practice to display items

I would like a suggestion.
I'm developing a web app using react-js as frontend and firebase as backend.
For sake of semplicity, say the aim of the web-app is to allow the user to upload some items which are then displayed on the homepage
An item consists of two string: 1) name of item 2) url pointed to an image stored on IPFS
Once the user submit a form, the frontend creates a new doc in a collection in firestore:
await addDoc(collectionRef, newDoc)
Then, in the homepage, I display all the items in the collection
const querySnapshot = await getDocs(collectionRef);
querySnapshot.forEach((doc) => {
...
});
This works; however, if I've understood properly, every time the homepage is refreshed the frontend makes N read calls (where N is the number of docs in the collection). Therefore, I'm wondering if its the right approach, is there a better way?
I really appreaciate any suggestion (also regarding potential major safety flaws in this setting)
Every time the homepage is refreshed the frontend makes N read calls
(where N is the number of docs in the collection).
With const querySnapshot = await getDocs(collectionRef); this is indeed the case: all the docs in the collection are fetched.
If your collection contains a lot of documents and is fetched frequently this will cost you money and, at one moment, the performance of you app may be degraded (duration of the Firestore query execution and lot of docs transferred from the back-end to the front-end).
One approach to avoid that is to use pagination and fetch only the first X documents and display a link to fetch the X next ones, etc.
There is a page in the Firestore documentation dedicated to pagination implementation.
You could also implement an infinite scroll mechanism instead of a link, to load the next set of X document continuously as the user scrolls down the page. That's just a UI variation and is based on the exact same approach detailed in the Firestore documentation.
Also regarding potential major safety flaws in this setting
Fetching all the docs of a collection or using pagination does not make any difference in terms of security. In any case you should implement security according to your requirements by using security rules (and potentially Firebase Auth as well). And don't forget that security rules are not filters.

React+Javascript:-Component will update is getting called too many times causing my application to crash

componentWillUpdate() {
//Axios GET method for getting all the trades
//Adding data of db into mobx store/or syncing data of db and store
axios.get(`http://localhost:8091/trade`)
.then(res => {
this.props.store.arr = res.data;
})
}
This piece of code causing my browser to crash, my laptop to not responding.
Actually, whenever i was trying to delete the row of table containing trade by click of button then the trade was deleted but it took the need of refresh to see that the trade is deleted.
This was because my mobx store and db were not in sync.So as soon i refresh the (REST api) controller updates data in my mobx store.After this i can see that trade is deleted.
So in order to remove the need of refresh i thought to use component will update method.Within that method i tried to sync mobx store with controller data (db data).It worked but it caused the browser to take more than 2.5 gb of memory & at this point all the running applications starts getting crashed also.
So what is the good way to achieve the desired result?
Note i don't know why component will update is getting called too many times.
But i can verify the it because i can see the selection statements(of database) in spring (my server which is sending data to controller ).
Putting the above code inside component did mount is not removing the need of refresh but it is not causing the browser to crash also.
You should not be doing this type of operation in this lifecycle hook. You should use componentDidMount instead for any remote calls that need to happen. However since you are using mobx, you really should not be having these problems as they handle these type of problems for you with the observer pattern. Please read: https://mobx.js.org/getting-started.html to get up to speed and you should have no issues at that point.
Something in your component's props or state is causing it to update often, which is causing a lot of calls to the api. Your best bet would be to find out what is causing those updates and use nextState and nextProps arguments supplied to componentWillUpdate to check and send an api call only when needed. Something like:
componentWillUpdate(nextProps,nextState) {
if (nextProps.needToGetApi !== this.props.needToGetApi) {
//Axios GET here, so that unrelated prop/state change does not cause this to run
}
}
Hint: Add a breakpoint in componentWillUpdate and see what props or state mutations are happening on each call.

Categories

Resources