React.js aggregate state changes? - reactjs

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.

Related

Updating async storage/data store in real time

I have a react native application where a user can edit a text which is stored in react state. I would like to implement autosaving so that user input is persisted in real time.
I have replaced my state with async persistence but have found that I am running into a race condition:
My parent component fetches the text from persistence.
The user inputs new text, which triggers a callback to update the given text with the new content.
If the user inputs text too quickly, before the persistence has updated and my parent component has fetched the new, updated text, the next async update is triggered on the old text, causing a conflict.
In particular, this happened with AWS DataStore. I have not tried using async storage, but given it also uses async/await I imagine I will run into the same problem.
A hacky approach would be updating at longer intervals but I'm assuming whatever interval I set will be long enough that each async update completes before the next. It's also more complicated as I have to keep local state which contains what the user sees while syncing that with the async storage/DataStore in the background.
Is there a nice way to replace react state with a persisted version that doesn't require a load of extra logic handling async race conditions? In an ideal world, some sort of usePersistedState hook which manages this all for me, exposing the exact same behaviour as useState?
To give an example of the race condition, say the text is a, and I type in b followed by c:
First DataStore update: a + b
(Expected second DataStore update ab + c)
Actual second DataStore update if input is too fast: a + c
DataStore result is some conflict, e.g. merging both updates to produce abac

Force React to treat an update as low priority

I see that react 18 has some cool hooks to help manually control the priority of state updates (useDeferredValue and useTransition) and using these methods fixes some performance issues that I have on a table. But React 18 isn't stable yet!
So I am wondering if there is a way to handle this is React 16 / 17? Is there a way to tell the reconciler to tag my row updates as low priority so that a user's typing updates will always interrupt and take precedence over the table rendering the rows?
For a tiny bit more context, my issue is that I have a search box and a table on a page. The initial data displayed in the table rows is unfiltered, but when the user types in the search box, I make a query to the backend and get a filtered list of data. When that data comes back, I render it into the table.
I can (and do) use a debounce on the query so that only if the user stops typing for 500ms do I fetch data. But this only helps when the user is typing faster than 500ms per letter AND it adds 500ms to the user experience of retrieving the data on every single call. I'd like something that feels more responsive.
The React 18 updates solve my problem perfectly. Looking for a way to do this in React 17.

Next.js - SWR hook question about dedupeInterval and refreshInterval

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.

Subscribing to Redux - React props issue

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?

How to be sure that the react-redux app is rendered based on the latest request?

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.

Resources