I have a simple list component that show all the records. When it mounts, it call GET to get all the records from the DB then store it in the state.
There's also a dialog that i can use to add a record. After i add a record, there're two ways to update the list:
Call GET again and reload the whole list.
Push the new record obj into the component state.
Which approach should i take?
Depending on the project, I would most often prefer approach number 2 since it results in the best user experience.
Approach 2 saves the client from making an unnecessary request. Approach 2 will result in quicker feedback to the user after the add record request.
Related
How can I invalidate a single item when working with useInfiniteQuery?
Here is an example that demonstrates what I am trying to accomplish.
Let`s say I have a list of members and each member has a follow button. When I press on to follow button, there is a separate call to the server to mark that the given user is following another user. After this, I have to invalidate the entire infinite query to reflect the state of following for a single member. That means I might have a lot of users loaded in infinite query and I need to re-fetch all the items that were already loaded just to reflect the change for one item.
I know I can change the value in queryClient.setQueryData when follow fetch returns success but without following this with invalidation and fetch of a member, I am basically going out of sync with the server and relying on local data.
Any possible ways to address this issue?
Here is a reference UI photo just in case if it will be helpful.
I think it is not currently possible because react-query has no normalized caching and no underlying schema. So one entry in a list (doesn't matter if it's infinite or not) does not correspond to a detail query in any way.
If you prefix the query-keys with the same string, you can utilize the partial query key matching to invalidate in one go:
['users', 'all']
['users', 1]
['users', 2]
queryClient.invalidateQueries(['users]) will invalidate all three queries.
But yes, it will refetch the whole list, and if you don't want to manually set with setQueryData, I don't see any other way currently.
If you return the whole detail data for one user from your mutation, I don't see why setting it with setQueryData would get you out-of-sync with the backend though. We are doing this a lot :)
Is there a better way to implement million options in dropdown. In my case there can be more than one million users and I need to select one user at a time. I have one choice, make asynchronous call for each letter when typing and I can filter the users. Is there any other methods to implement? If I bind all the options to dropdown, will it make my app slow?
You can do it in 2 ways. One is what you already said yourself. Making async calls. Or you can also do it a simpler way, This will still have a huge performance boost. It is still not very advisable to filter on the client-side for a million items. But nonetheless, it's possible and I haven't seen any major performance hit.
Use a state variable to maintain what you are going to render and another static variable to maintain your entire million collection.
On search, you filter that one million list and assign it to the state variable.
Render only the items that are in the state variable.
Tip: Make sure your filter method doesn't return more than say, 1000 items at any moment, this will force the user to enter more characters to search and it will keep the UI smooth.
Yes, having a big list to render will make your app slow as it will have to mount and unmount when the user is typing. Ideally the client should send requests to server by using debounce or something to limit the requests and server should send a paginated response / top X number of users which match the input.
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.
So I am tasked to build an application where each component(5 components) has 1 editable table(components have no hierarchy). I am required to record the edits made in each component and make an AJAX call to a backend. The data that I send is going to be the edits from all the 5 components. What is the best way to approach a situation like this one? Thanks in advance.
I think that all comes down to where you put the sate, if you put on top of the hierarchy you will be able to spread to all children when the state changes
Alright what I did end up doing is to store things in localStorage and retrieve them when appropriate.
I'm pretty new to React / Redux, but love to play with it so far.
I came accros something that actually bothers me, but I'm not even sure it's a "real" issue I should care about. Anyway, here it is.
Let's say I have a component, which is actually a form for updating a record, retrieved from a database. This record has several foreign key to different tables. (Let's say my main table is Training, which has a Format, a Type, a Place... and all those data come from another tables).
In order to be able to display all the possible values for each of the foreign key to the user, I have to request all the different tables to get the data, and display those in dropdowns.
For now, I'm doing something like :
dispatch(new CrudActions(places).getAll());
dispatch(new CrudActions(trainingFormats).getAll());
dispatch(new CrudActions(trainingTypes).getAll());
Each of these line will dispatch a redux action, and so, update a part of the state, according to the data that is retrieved.
Then my component will then simply get the values from state :
function mapStateToProps(state) {
return {
places: state.places.list,
trainingFormats: state.trainingFormats.list,
trainingTypes: state.trainingTypes.list
}
}
It's actually working, but the consequence is : each time an action finishes and updates the state, my component get re-rendered... Let's imagine my main training has 10 foreign keys : for a single page load to display the update form, my component will be rendered 10 times.
Wouldn't it cause bad performances ? Is there any better way to retrieve foreign data ?
Let me rephrase that. Each of your record components has dropdowns for places, training format and training type. The dropdown options are retrieved via ajax. When you have several records, there will be a lot of requests and rerenderings.
The solution: Don't let every record component retrieve the dropdown values on its own. For each respective dropdown, they are all the same anyway. Instead load them in one of the parent components and pass them to the record components as properties, for example as availablePlaces, availableFormats, availableTypes.
Your parent component does not even have to load the available dropdown options via ajax. It can be initialized with it.
For further optimizations concerning rerendering have a look at https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate.
Facebook recommends making ajax calls in https://facebook.github.io/react/docs/react-component.html#componentdidupdate.