I'm using SWR hook along with next.js for the first time and i've tried to get some answers about something but i couln't get them, not even with the docs.
Questions: So, i know SWR provides a cache with your data, and it updates in real time, but i'm kinda lost between two options that you have to use the hook. So, normally, you have dedupeInterval and refreshInterval
refreshInterval = 0: polling interval (disabled by default)
dedupingInterval = 2000: dedupe requests with the same key in this time span
Now, what are the differences between these two ? if i have two request with the same key, it will update after two seconds ? is it the same as refreshInterval ? if i use refreshInterval, would i have problems with performance ? since it's making a request in very short periods of time
If you can help me with this, it would be great !
Thanks for your time !!
Now, what are the differences between these two ?
The difference is that:
refreshInterval is defining a time after which a new request will be sent to update your data. eg. every second.
dedupeInterval is defining a time during which if a request was already sent for a specific data (ie. a data having a specific key), when rendering a component that asks for a new request to refresh that data, the refresh will not be done.
Deduplicating means eliminating duplicates, ie. making potentially less requests, not more. They give an example in their documentation with a component that renders 5 times another component called <Avatar /> that uses the swr hook. But the actual request will be made only once because that rendering will be within the default 2 seconds time span.
If i have two request with the same key, it will update after two seconds ? Is it the same as refreshInterval ?
No, the dedupeInterval set to 2 seconds will not automatically update the data. It will update it only if a component using the same key with the swr hook is rerendered after the 2 seconds. Or if you haven't deactivated other updating mechanisms like on focus and the user puts the focus on your component.
With refreshInterval there would be an API call every X amount of time, as long as the component is still mounted, even if it doesn't rerender and the user doesn't interact with it.
If i use refreshInterval, would I have problems with performance ? Since it's making a request in very short periods of time.
Yes, if the user opens your page and does nothing but reading content during 20 seconds, and you have set the refreshInterval to 1 second, there will be 20 API calls to update that data during that time. That behavior may be useful if your data changes every few seconds and you need to have the UI up to date. But clearly it can be a performance issue.
The reason why the refreshInterval is disabled by default whereas the dedupeInterval is set to 2 seconds is to avoid too many API calls.
Related
If my data is coming from a url (xml or json) and from that data I have to set the state of my react component. The thing is that data is chaning every 5 to 10 seconds. Its data of traffic passing from a certain location where police thinks that people do over speeding alot. so I have to use that source for setting my state in react and display the cars registration number if speed is more than 100km. So data, (speed, time, registration number) of the vehicals i am getting from url online and it changes. So I want it dynamic, means when it changes, it should be updated in state too.
so should I have to make a call of initializing (componentDidMount) for exmple 500ms or something like it, and how?
I havent tried anything yet, cuz I am confused how to do it.
Webpack has an option that is called aggregateTimeout, this is explained as:
aggregate any other changes made during this time period into one rebuild
So the idea is, how can I bundle multiple changes within time period e.g. 1 second; to a single state update?
For example I have an editor in my react app, it updates the state each time the user types text on the editor, but I found that it makes the app a little laggy. So I want a timeout that ignores text inputs within, let's say 500ms, and it only updates after 500ms passed since the last time the user did text input.
How can I implement something like the case? Thanks.
I'm trying to build a little calendar, where one can "mark" days by clicking on them.
Each click causes a request to the server to persist the change (set or unset a day).
It seems like useState can only keep up with so many changes at once, and due to the nature of reloading the component, i loose some of the fetch-requests happening as well.
When i understand the useState behavior correctly, each setDays will reload the whole Calendar, even if an instance still has a request running. The system is smart enought, so that a (limited) number of requests still manage to complete in the background and trigger their state update. However i have no control or guarantee over how many "make" it when clicking fast.
My real code has an additional state change, by marking/unmarking each day as "in flight" (via dayClassName) while the request is running, probably increasing the problem even more.
I'm a bit lost in what direction to go from here:
Should i try to limit the effect of a day change to a single day itself, avoiding to update the whole calendar with every click (need the result outside, though).
Or is a different system/strategy to manage the state, e.g. redux, the better choice here. For example to serialize the updates into one stream.
Update:
Here is a codesandbox with example: https://zpvy0.csb.app/
I tried to get as close to the real thing as possible, unfortunately i still can't reproduce the issue. It seems like react/useState is not the issue, as in the codesandbox it works reliable with 30+ requests triggered at once.
Update 2:
I have rewritten my code using the codesandbox version as base (re adding what other functionality/styling, etc was there). Now everything works perfectly.
Currently i have no idea what difference was causing it at the end.
If I'm understanding your issue correctly it sounds like the issue is that addDay and removeDay are called in quick succession and you are losing some state updates. You mention users clicking "to fast" so it may be the case that more than 1 state update is being enqueued. Since you are using plain updates if 2 updates are enqueued within the same render cycle the second update overwrites the first. If more get enqueued then each subsequent processed update overwrites the previous. Hopefully you get the idea here.
The resolution for this is to use functional state updates so each enqueued and processed update updates from the previous state, not the state the update was enqueued in. This means if multiple updates are enqueued in a render cycle each update/change is applied sequentially and the result aggregated state update is available for the next render cycle.
Functional Updates
If the new state is computed using the previous state, you can pass a
function to setState. The function will receive the previous value,
and return an updated value.
The previous state is an array and you are updating from that array when appending new day objects. It's a very minor tweak.
const addDay = async (day) => {
await makeRequest(day);
setDays(days => [...days, day]);
};
const removeDay = async (day) => {
await makeRequest(day);
setDays(days => days.filter((d) => d !== day));
};
So I need to implement this function that checks the Redux variable in interval, say 5 seconds. My issue is that this variable is the content of a large, editable text; so subscribing to it normally causes app lags (because every typed letter is a variable's change).
Does anyone have an idea how to overcome it? I can post some code if you want, I just thought it's rather a theoretical problem..
Maybe I can render this component just every 5 seconds to avoid it being connected constantly?
I have a react-redux application which:
Loads N records from the database depending on a "limit" query parameter (by default 20 records) on first application load (initialization)
Every 10 seconds app requests same (or newer) records from the database to update data in real time
If a user changes filters - app requests new records from the database according to the filter and re-renders app (+ changes interval to load data according to the filters)
If users scrolls down, the app automatically loads more records.
The problem is that if a user for and instance tries to filter something out and at this same time interval is loading more data, 2 requests can clash and overwrite each other. How in react-redux app I can be sure in a request sequence. Maybe there is a common approach on how to properly queue requests?
Thanks in advance!
I am not sure what you mean by 'clash'. My understanding is that the following will happen:
Assuming that both requests are successful, then data is retrieved for each of them, the redux state will be updated twice, and the component which renders the updated state will render twice (and the time passed between the two renders might be very short, which might not be very pleasant to the user)
If you want only one of these two requests to refresh the component, then a possible solution may be the following:
Each request starts, before retrieval of data from the database, by creating a 'RETRIEVAL_START' action. 'RETRIEVAL_START' will set a redux state variable 'retrievalInProgress'
If you want, in such a case, to get results only from the 1st of the two requests, you can check, before calling the action creator from the component, if 'retrievalInProgress' is on. If it is, don't call the action creator (in other words, do not request data when a request is in progress). 'retrievalInProgress' will be cleared upon successful or failed retrieval of data.
If you want to get results only from the 2nd of the two requests, then make 'retrievalInProgress' a counter, instead of a boolean. In the 'retrievalSuccess' action of the reducer, if this counter is higher than 1, it means that a new request already started. In this case, do not update the state, but decrement the counter.
I hope that this makes sense. I cannot be 100% sure that this works before I test it, which I am not going to do :), but this is the approach I would take.