I'm currently using React (with hooks) and Redux-Toolkit. After reading through the docs, I've come across Redux Thunks, createAsyncThunk, and RTK Query. Out of these three methods, which is the best for fetching data in a Redux slice, modifying that data within the slice, and then dispatching said data to a React?
Thanks in advance for your answers!
Each of them serves its own purpose, and only RTK-Q is made exactly for data fetching and caching.
The "problem" is that it's
Not really integrated with the application store's Redux and Thunks by default - it "lives" in its own store, with its own cache state, actions, and middleware.
The idea is that you don't want to put fetched data in your app-store, course, it will just duplicate the data and add another "source of truth" with the following inconsistency.
RKT-Q adds a concept of "API state", which represents the data on the backend, and should be handled significantly differently than App's (frontend) state.
In extra cases, you may handle the RTK-Q-related actions, handle them in your middleware (Thunks in your case) and update your Redux app-state producing actions with some calculated data\flags, etc.
Not covering all the cases of Application <-> API negotiation.
As an example - file\data export, API action calls, and other stuff that is out of RESTfull architecture. If you'll try to download a file from API via RTK-Q you'll find how bad it's covering such a case, and you'll be forced to use separate flow via Thunks\Sagas or\with plain fetch API to do so.
But still, RTK-Q brings you so much out of the box, so it is worth using it by default for data fetching, even with some work to handle several edge cases.
Wrapping up - I believe that there is no right\complete answer to your question and just more things to consider for your own app architecture design.
Related
I'm getting back to using React now after a long time of not touching it, and I am looking at the redux toolkit which I've used before, and I see RTK query.
I'm trying to understand it, and think I have, but there's one thing I'm not sure if I'm missing or it is just designed to work like that.
Do we only use the RTKQ to fetch data that we don't need cached at all? For example loading a specific post that the user clicked on? I'm asking because in any tutorial I've watched or read I haven't seen any interaction with the other slices.
If for example I need to get some information that needs to be kept (otherwise I'd just keep fetching it), then I will use the regular createAsyncThunk?
It's the other way around entirely.
RTK Query is only for caching fetched data.
It's always been common to fetch data from the server and put it into the Redux store, but it takes a lot of work. You have to write thunks that make the request, dispatch actions based on the results, and write reducers that manage loading status and save the cached data. Then you have to write useEffect hooks to dispatch those thunks from components, and selectors that read the data from the store.
RTK Query does all of that work for you, automatically. And it then improves on those basics, by fetching new data when arguments change, refetching query data automatically when you send an update to the server, managing cache lifetimes and removing old data when components no longer need it, streaming updates, and much much more.
I'd recommend going through the relevant sections of the official "Redux Essentials" tutorial in our docs, as well as the RTKQ usage guides:
https://redux.js.org/tutorials/essentials/part-7-rtk-query-basics
https://redux.js.org/tutorials/essentials/part-8-rtk-query-advanced
https://redux-toolkit.js.org/rtk-query/usage/queries
As I understand if we make a request by using redux-saga, the response is going to be stored into the redux store. But it is a bad practice to store all the stuff in the redux store. So is it ok to create separate module with API requests and use them when you do not want to put response in redux store ?
I would appreciate articles on this topic (couldn't find it on my own).
Making requests in a file is totally fine in some cases. Just do it carefully in order to prevent interfering with app performance (if a component is rendered multiple time and you need just one request do it in the parent, etc.)
As for articles I couldn't find any to exactly this topic, but react docs have an example of api calls (please ignore the class one and check the hook example bellow). Now I would recommend you too use a service for this to abstract the fetch logic, but the idea is there and, while this cases shouldn't happen a lot, I don't see any reason to avoid this if you only need some data in a specific component and there is no use in saving it to the state .
EDIT:
You have runSaga which according to docs
Allows starting sagas outside the Redux middleware environment. Useful if you want to connect a Saga to external input/output, other than store actions.
So you don't really need another library. Regarding the architectural problem this is what I was trying to emphasis with the react docs. I don't know if there are any articles in this direction (on a quick search I couldn't find any either), but I think for most of the data you want a reducer to prevent unnecessary reloading of the same data.
However there isn't anything suggesting not to do it as far as I know (neither in docs, articles, etc.). Moreover, in some cases, this can a good thing, and the fact that no docs suggest otherwise is a prove in this direction IMO.
PS: Also a discussion about using saga without redux here
currently I am using redux in different projects for state management. A few days back, I listened about react-query which is also used for state management and provides caching and async fetching. I am trying to figure out the main difference between these two libraries.
Where I should use react-query and in which cases I need redux.
React-query is what you would call a specialized library. It holds an api cache for you - nothing else. And since it is specialized, it does that job quite well and requires less code.
Redux on the other hand gives you tools to just about store anything - but you have to write the logic. So you can do a lot more in Redux, but you'll have to potentialy write code that would not be necessary with a specialized library.
You can use them both side-by-side: api cache in react query, rest of your global state in Redux.
That said, the official Redux Toolkit also ships with an api cache abstraction RTK Query since version 1.6 with a similar feature set as React Query, but some different concepts overall - you might also want to check that out.
react-query is designed to deal with data that is stored on a remote server. To access this data, your app needs to use asynchronous requests. This is where you probably want to deal with caching, loading state, network failures, etc.
That is where react-query shines.
Redux on the other ends deals with data on the client-side. For example the content of a text input or the state of a modal. You don't need to deal with network-related issues. But you do need to deal with complex sequences of causes and effects.
That is where redux shines
Redux and react-query are 2 very different things: react-query is used for data synchronization, Redux is a global state manager. react-query is used to keep synch all your apps to the same db, Redux is used to share a part of the app state to all the components that need to read that state.
An example: I have an app to chat with other users. With react-query I keep all the apps synch with all the messages users received, then I store the messages in Redux in order to have messages on chat page and on history chat page.
React Query manages Server State. Its main function is to handle functions between Server and client.
Redux handles client-state. Redux can be used to store asynchronously Data.
So, they have their unique role at different levels and both can be used side by side.
React-Query = server state library(save/cache api response)
Redux = client state library(globally accessible client state
should be stored).
We should distinguish between two kind of states, client state & server (or remote) state:
client state contains:
locally created data that has not yet been persisted to the server.
UI state that handles active routes, selected tabs, spinners, pagination controls, and so on.
server state is everything related to:
data persisted remotely that requires asynchronous APIs for fetching and updating
When it comes to client state, Redux is a grate management tool for managing application’s state.
On the other side, to manage server state, we can use regular state management tools but they are not so great at working with async or server state. So, to resolve this, we use React Query. As described on their documentation, React query is a great tool for:
Caching... (possibly the hardest thing to do in programming)
Deduping multiple requests for the same data into a single request
Updating "out of date" data in the background
Knowing when data is "out of date"
Reflecting updates to data as quickly as possible
Performance optimizations like pagination and lazy loading data
Managing memory and garbage collection of server state
Memoizing query results with structural sharing
You can simply to think:
React Query = axios + cache logic
Redux can store synchronized data and asynchronized data
By the way, I use context manage synchronized state, React Query manage asynchronized state now.
It opinions based questions .
Need one suggestion.
In Reactjs, is it right approach to use redux for state management and for API call use Apollo + GraphQL?
You have to distinguish between view state (e.g. search field, popup, toggle) and data state (e.g. remote API). Whereas Apollo is mainly used for data state, Redux/MobX/React's Local State are used for view state when used in combination with Apollo Client. If not used with Apollo Client, these solutions can be used for the remote data state too. However, Apollo Client introduced apollo-link-state which can be used for the local view state too.
If your application is purely remote data driven and uses a GraphQL backend, Apollo Client can be sufficient for your application.
If you have a few view states in your application, mix in React's local state management.
If you have several to a lot of view states, use Redux or MobX for your view state or try out apollo-link-state.
That's certainly possible and the natural thing to do. We use this same setup and we found we don't have to use Redux very much anymore.
We used to use Redux to store our API responses (the data) as well, but now Apollo manages that for us.
So our Redux store is now only used for the actual UI state (e.g. routing state, user preferences for certain views, whether something is enabled or not etc).
All data is now retrieved by Apollo and kept in its own internal Redux store, which it uses as a cache. This works great and nicely separates UI state from data state.
I suggest Apollo GraphQl because it has many benefits:
Eliminate Boilerplate
No more action creators, async handling, and request waterfalls. Just ask for the data you need with a GraphQL query, and it shows up.
Validation across the stack
Identify breaking changes in your API before they are deployed, and statically validate data fetching across all of your frontends.
Understand API usage
Learn how your backends are being used with field-by-field granularity. Find and address performance hotspots easily.
Pull complexity out of the client
Put computed fields, data transformations, and security logic into your API so your frontends don't have to reimplement them every time.
Incrementally evolve your API
Add fields to GraphQL as you go and deprecate old fields when you no longer need them. Mock some or all of your API and build the frontend in parallel.
Improve performance
Fetch exactly the data you need, no more and no less. Improve performance with GraphQL-specific caching and optimizations across the stack.
For more Information Read GrapQl Apollo Doc
https://www.apollographql.com/docs/
So I may be asking the wrong question, so please leave comments and I'll adjust. I was told by another developer that when using redux, I should do ALL API calls within actions and create reducers for them. But I feel that sometimes making the call directly in the component will save me a TON of code. Are there best practices for this sort of thing?
If the data you are getting from the API is only going to be consumed by a single component then you are fine to write it as part of your component (or better still, a container component). I believe the rationale behind doing your API calls in actions is to ensure that the single source of truth is maintained (the main reason to use 'the react/redux way' for me personally). If you are bringing in data from your API that is to be consumed by multiple components then use redux to ensure the same state is maintained by redux and passed to all components that use it.
This was previously answered by Redux's creator, Dan Abramov, here: Why do we need middleware for async flow in Redux? .
The summary:
It’s just inconvenient in a large application because you’ll have different components performing the same actions, you might want to debounce some actions, or keep some local state like auto-incrementing IDs close to action creators, etc. So it is just easier from the maintenance point of view to extract action creators into separate functions.