React / Flux - fetch all data after every update/add/remove - reactjs

I'm learning React and Flux and there's something that bothers me about all the examples I've seen so far.
They all are pretty much a CRUD UI.
In them, they always fetch all the data after every change (update/add/delete etc.)
So let's say, we have a todo app, and the user added a new todo item.
In a response, the store will get an action, call some API in the server to add the item and then fetch all the items again.
Isn't that expensive?
I understand why it makes things simpler which is good. But, why not add the item to the store's state. I understand this makes it so you always have the keep the store and the data in the server synced like that but it's not as expensive.
One solution I saw was pagination but in the example they would still get all the items for the new page every time a user changes it.
Why always fetch all the data?
If we use pagination - would we get the new page from the server every time a user changes pages?

It is not necessary to get data after every change. In the apps that I have built, I have always changed the store rather than get all data.
In only one project which involved DreamFactory API, we used to refresh the model (only that model/item) after an update. That was necessary because DreamFactory API pulls all the related data in a single call.

Related

What's the Best way to Reduce Mobile Data Usage in React and React-Native Apps

Data usage really matters for my targeted users. So, I am looking for an APPROACH that'll help me reduce the number of data fetching during react rerender cycles in React and React-native App.
Let's say I have a page that renders all the Items fetched from an API. Since the API's data can be updated at anytime, I am obliged to re-call the API whenever the user displays this page.
IS THERE ANY WAY FOR ME TO KNOW THAT THE DATA HAS BEEN UPDATED WITHOUT BEING OBIGED TO RECALL THE API?? Because I think that the less HTTP requests I send the less mobile data I consume (Maybe I am wrong... I don't know)
I thought of implementing a solution with Redux and Socket.io :
I wanted to prepare an event called data-updated that will be managed by socket.io and whenever one of the users performs an action that updates the item lits (The API data), the data-updated event will be triggered and all the connected users will be notified. Then in the data-updated event handler I will update the item list state slice in the redux store.
My worry is that since socke.io keeps the connection between users and the server alive during the whole session, Won't this approach consume even more Mobile data than recalling the server at any rendering??
You can proceed with graphql with mutations and its caching mechanism, its pretty cool and if I mention if it is handled efficiently you can run your application in 2g network also with speed. Checkout its usage and advantages over REST you gonna love it. https://graphql.org/
Another way is by using redisCache but personally I've not used it though you can check.
You can use React-query lib for data fetching, updating, caching etc.you can read more about it but read its docs.
https://tanstack.com/query/v4/?from=reactQueryV3&original=https://react-query-v3.tanstack.com/

What's the actual need for RTK Query when fetch API is provided?

Initially the idea of Flux is pretty obvious. The view gets Actions and then emits events based on the Action with which the store is updated. However, when I read through redux-toolkit it seems there are multiple ways of achieving something that should be trivial, namely getting JSON data from an endpoint:
Use the fetch API to get some data from an endpoint
Use RTK query to do the same
Use the React Context API
Using the useEffect() hook
Why are there so many different ways for achieving the simplest task?
Thanks.
This question hides a lot of sub-questions, so I'll try to answer them all as per my experience ( I'm partially a fan of RTK Query ).
To ask for a resource via HTTP from a browser there are not many ways, you have to use xhr or fetch API.
xhr is the old callback-based API, fetch is the modern standard promise-based API.
On top of these APIs many libraries were born to make the process and configuration easier/wider, today you mostly will work directly with fetch or with some gold-standard libraries like axios which is pretty similar to fetch but it has some cool extra features to handle the fetch calls and configuration.
On modern frameworks/libraries like React the problem is not How to retrieve a resource via HTTP, but how to handle the asynchronous call and the side effects that the response creates to the whole application.
So now this opens up to the several options you enlisted.
Basically for very basic fetch calls, you can handle the call inside
a useEffect if it's a GET call that has to retrieve data to show
inside the component that just mounted automatically, or
imperatively start the fetch on a button click for example if it's a
( usually ) POST,PUT, ecc... call.
You can then save the result in a React state, and furthermore pass it throughout your application with a context to let other components access the received response. By the way this leaves you with a lot of other behaviours uncovered, the first one is the loading state during the call, and the error management in case of bad status response or other exceptions. That's surely something you can implement briefly with a useState or better a useReducer hook, by the way, so that's not the real reason why you will feel the need for some async calls manager like RTK Query.
REVALIDATION
What happens if for example you are doing a post call on login of a user that returns the user object with user data, you save that data in a client side state manager ( or React state ) and use that state to display user data in your whole application. During the usage of your application, the user can perform some operations that change his data on DB, so you have to take care everytime he does that, to refetch his data and update his clientside data object, or to return the new user object from each POST/PUT/PATCH etc... call and update the clientside state which is pretty error prone, since you might find yourself having an unsynced clientside/serverside data state if you forget to update the clientside state after each operation, or if there's some issue during these phases. This can often lead to pretty hard to manage and to debug situations.
I'd say this is the First good reason to start using a Fetch manager like RTK Query.
This manager implements a pretty straightforward Tags based revalidation mechanism, that let's you to assign a tag to each Query ( GET ) that you perform, so for example you will make a query when the user logs in that retrieves the user data and you will tag the data with providesTags: 'User'.
Now you can safely perform any number of mutation on your user data on backend, and to each one, clientside, you will tell that as soon as it gets a response, it has to revalidate a certain Tag ( or multiple ones ). For example you might have an editPasswordMutation that changes the user password inside the database, and you will just add a invalidatesTags: 'User', this means that as soon as the user receive a positive from the server confirming that he updated the password, the client knows it has to reexecute the getUserData call, get fresh user data, and save them into the redux global store, so they will be immediately accessible to all the application components that are consuming them.
Totally authomatic.
This whole mechanism would definitely need you to write much more code if you were to implement it yourself.
OPTIMISTIC UPDATES
Most of times you will find yourself not wanting yor UI to wait for server response before showing the effect of a ( for example ) button click. Imagine when you click a thumb up on Facebook, you immediately see it in your UI, and that's not cause they have super fast servers, but because the UI is assuming that the call succedeed as soon as you click the button so it instantly adds a +1 to the likes count of the showed post.
This behaviour is not trivial, since usually when you show data in your application you have and should have a single source of truth. So for example if you are rendering a list of blog posts, you should have retrieved them from your backend database, saved them in your clientside state manager or directly render them as-is. If the first post has, let's assume 10 likes, you will render them based on data.posts[0].likes.count. So that's your source of truth. If you want to add a Like/Dislike button, and you want to implement an optimistic update, you would have to manually alter that source of truth, which is not good at all since it could be shared across multiple components ( in case of a global state ) or to duplicate it, and alter the duplicate, but that's not good either.
It's almost never ( almost ) a good idea to duplicate a source of truth.
RTK Query to the rescue!
With RTK Query Optimistic Update is pretty straightforward to set up, basically EVERY fetch can implement an optimistic update behaviour, since you can use the life-cycle method onQUeryStarted to intercept the immediate start of a call, and then use the utility : updateQueryData to update the data that your mutation is going to invalidate. Extremely SMART.
So in this case you will just have a simple mutation that will add a like to the blog post, that mutation will invalidate the posts data, the single post will be immediately updated in the UI with a +1 like, meanwhile the server will refetch the posts list ( since they were invalidated ) and fresh data in sync will be retrieved, and the user will notice just a pretty smooth experience.
There are many other features, especially involving Cache management, which are a plus, ( even if sometimes they can create some issues ) but I highlight these two main features that alone pushed me to become a user of RTK Query, it might look a bit verbose at start, but it definitely makes things pretty clean and tidy, coherent with the Redux philosophy.
As per docs, the goal of the tool is
It is designed to simplify common cases for loading data in a web application,
eliminating the need to hand-write data fetching & caching logic yourself.
It provides some caching and I personally find it very convenient to have declarative isLoading/error without the need to useState for all of it every time : )
But again, it's only optional: RTK Query is an optional addon included in the Redux Toolkit package.
There are multiple ways to achieve the same goal indeed. There's no gold standard in React world regarding this, for better or worse.

Is it possible to split a GraphQL query into separate react-query caches

I have been using React-Query for a project work and I absolutely love it (actually replaced redux with it since 99% of the state was just server state).
I have a question though that I'm not too sure about.
The project itself is a dashboard of widgets. A dashboard could potentially have 10+ widgets on it.
We are using a GraphQL api so it's possible (and ideal) to make a single api call when the dashboard loads with each dataset we need and pass the relevant data to each widget. Using react-query, this would be ONE query, so all widgets would be subscribed to this single query.
The issue is we want to add features such as 'refresh', 'filtering' and 'pagination' to each individual widget, which would involve api calls just for that one widget, but as the entire dashboard of widgets is subscribed to ONE query, the whole dashboard would refresh etc.
Is there a way to:-
make a single graphql call on initial load to get potentially 10+
sets of data for each widget
have each widget be subscribed to their own individual dataset
(separate query)
I have seen on the docs that we get access to the query client and could potentially use an onSuccess function to 'setQueryClient' to a selection of individual queries but I've read that this isn't a good approach and that 'setQueryClient' should only be used for optimistic updates.
Hopefully the above explanation makes sense, and any tips would be greatly appreciated.
It sounds like you want to make one request on the Dashboard for all widgets, and then render them. But instead of passing data down, I would make another useQuery inside each widget, which would only get data for that widget. You can prime the cache for that query with initialData, where you can pull out the data for that widget from the dashboard query. That way, you’ll get the data from the dashboard query for the first render (and no additional loading state), but each widget is still only subscribed to its own data. Don’t forget to set a small staleTime, or you’ll get an instant background refetch :)
Alternatively, the select option will also work well in terms of optimized re-renders, but there will always be the "big" request that fetches all the data for all widgets. If they all need to refresh at the same time, this is also a good option.

React | working with remote data advise ( a conversation )

I've taken the program at Udacity for react and react native, and it taught me well id say.
Now that I am equipped with the skills and have a good knowledge of the environment and redux etc. Im trying to build my first test app that handles data living remotely.
In the React tutorials we would use local mock data, and try to fetch it and even simulating the delay with a setTimeout call. But the problem is the tutorials worked excellent only for the types of apps they were building. I'll get to this in a bit...
My app description:
At the moment i'm making a test app and so far I can : retrieve a collection of food items ( remote data), render the data, and press "LIKE" on anyone. After pressing Like that food item URL gets saved into another remote file under the authedUser's account under a "favorites" property.
The food data at the moment is in a json file hosted on a github repository.
and so is the users account data.
The thing I noticed in the react course was, Data would be received into the redux store.
from there anytime you dispatched an action which involved data changes like "Favoriting" something, the app would first dispatch an action to server. Once that resolves it would dispatch to the redux store and affect it there.
Now from what I understand... this is a way to keep the data in sync? Is this how other applications do it? or is it when data is changed, you only dispatch the change to the server, and request/fetch the new data into redux once the action resolves? The tutorials would receive the initial data, and like this it would be set and stone and then rely on the dispatches to keep it in sync. would it be better to simply use local state, fetch the data we want. vs using the store?
Im not exactly sure whats best, but to me the idea of receiving the entire data file into the app seems not scalable? like when you use instagram for example, your phone doesn't download the entire instagram database. Im thinking it downloads only your profile? and url's to your friends? etc?
so for this test app that I am trying to make ( described in italic font above ^ )
I'm not sure how to go about it. I definitely don't think its appropriate to receive the entire data file. I know that I want the user to receive food items onto the screen, but only a handful at a time, maybe through a search it modifies the results on screen. then the user can like a food item.
This is the first time i'm working on an application of this sort, and I do think i'm missing something.
It would be a good idea to not integrate Redux at first. Just build the application in plain React.
Now talking about your app. As you said, is a bad idea to download the entire database. When you have to fetch a lot of data a common pattern is to use pagination. It works like this: your app asks for 10 food items. The server returns those 10 and tells you that there is more data and you should make another request if you want to fetch more. It doesn't make sense to fetch 1000 products if the user can see only 10 at a time, right ?
Let's say you like a food item. After you press "like" it is not enough to update your app state, you also need to make the change on the server. How you do this ? Usually you have a food item id(let's say 123) and you maybe you make a POST to https://server.com/like/123. Now that request may fail for various reasons and the server will not register your like. This is way you update the local state only after you successfully updated in the database. In addition you may want to update the number of the likes(maybe other users liked that food item since you fetch) so the server will return the updated number of likes.
Where does Redux fit here ? In React every component has its own state. They can share data between them using props. But this doesn't scale and you will usually end up in a situation called Prop Drilling. Redux store is some kind of global state. For instance:
<FoodItems>
<FoodItem key=1/>
<FoodItem key=2/>
</FoodItems>
Let's say somehow you update the description for the first FoodItem. How do you tell that to other components ? In Redux you dispatch an action and modify the store. Now other components can connect to the store and get the value from there.

Fetch update from backend or update redux

Imagine a React app where you can list your friends in a sidebar. The site uses Redux to store the state of the friends. In case a user adds a new friend to his list, I have to send a POST to the backend, to save it.
The question is, how should I update the list of friends in the sidebar?
After the post, should I make a GET request and add the response to Redux or should I just use the data and add it directly to Redux, removing the extra GET call?
My suggestion will be doing both. When you are making a request to server update the Redux store which will update your state(Friends list) and will rerender the component.
Also fire the GET request action, so that if there are data that are on the server but not in your redux, that should get retrieved.
(imagine: Using two machine at the same time and adding friends)
And if you are using something similar to a pure component, if your redux store and retrieved data are same, i.e., no new data was available on the server, there will be no change in state and component will not re-render. They will re-render only when there is a difference in state and will display the current list.
IMO both options are valid. However, I like to have a single source of truth in our applications, which is the backend in most cases.
Sometimes, you might even choose to go for both options. This will increase the user experience by preventing a loading state, but if the action fails or the backend data is different than your redux store, it can result in "weird" behavior.

Resources