I come from an Angular2 world where there are services that do the normal data loading and so on, now I am on a React, Redux application and am trying to figure out what is the equivalent to Angular2 services in Redux (React). Is it Redux-thunk?
The answer is yes and no.
Yes
Angular services have the logic to load data and normally return a Promise object that gets resolved with data loaded.
With Redux Thunk middleware, you create asynchronous action creators where you put the logic for data loading. But instead of returning a Promise object directly, it waits until the data gets resolved and dispatches an action to update the state with data loaded. React components receive data from Redux store via props. (See connect() method from react-redux.)
No
Angular services are singletons that provides a specific functionality, like $http for facilitating communication with the remote HTTP servers.
Redux Thunk is a middleware and does not do anything but to allow you to write asynchronous action creators that can delay the dispatch of an action, or to dispatch only if a certain condition is met. The action creators are functions that create actions - they are not intended to provide other functionality, like communication with backend servers.
With that said, it is often a matter of coding style where and how you write the logic to load data.
You can use the Fetch API or its polyfill function, or axios library, both are Promise based. You can also consider using Observables, but it is beyond the topic, I think.
As you do with Angular services, you can put all the related logic in a single location and export them. In your action creators, you call these wrapper/helpers, listen for resolution/rejection and dispatch an appropriate action with data resolved as a payload.
Your reducers update the Redux store upon receiving an action dispatched and these state changes are propagated to React components. And this is how the Flux architecture works and how the data flows from Redux Store to React components, AFAIK.
(I might be wrong, please correct me if anything is incorrect and I am open to your opinions. I am still on the way to figure out the best practice to implement services in React applications.)
Related
I was using axios for api calls in class component of React. And used Redux to store mostly login details.
So started learning about Redux-thunk and now I am confused as to where to do API calls? Is doing api calls from view side not good? Do i need to use redux-thunk?
You use redux-thunk when you require async actions for your reducers.
Calling an API would be a good example of that. Doing API calls is something the view would do, anyways (e.g., otherwise you'd have them in your components, which is "view", too). The API is then doing the business logic and is only providing "view data".
Your view might also want to track the state of the async action (e.g. "list is loading...", "failed to load because xyz", "{list of users when loaded}")
You don't need to use redux-thunk, but chances are at some point you re-implemented it, anyways (I did that and then switched). I suggest you simply use #reduxjs/toolkit (They have a good documentation site)
It really eases up working with actions, thunks, async thunks and reducers in general.
We are developing a React application using Redux to manage the state. In general, Redux serves us well, but in one part of the application, we are using WebSockets to update our app state to allow all the connected users to have the most recent version of the data.
It looks like this: https://i.stack.imgur.com/uNAsk.png
In a regular Redux application, we would have 3 actions: ACTION_LOADING, ACTION_SUCCESS and ACTION_FAILURE to handle HTTP requests. In this case, the state is updating automatically after receiving new data from the WebSocket.
Is it correct to have a Redux action (thunk) to post this data to the server even if it does not modify the state, or is it better to call the service without using Redux in these cases?
In case we create actions, what pattern would you recommend?
Thank you.
I would recommend wrapping it in a thunk for a couple of reasons:
There's nothing fatal about initiating an action that doesn't end up mutating state (for whatever reason).
Even if you aren't doing anything in the case of a successful POST (since all the action will come later via a message from the server), you still might need to dispatch an actions in case the POST fails for some reason.
It allows your components to use one consistent mechanism (action dispatch) rather than sometimes one way and sometimes another.
I have read everything I can find on how to use react-saga and redux-form together I'm stuck at a crossroads and need some advice.
Here is how I ended up here.
I chose to work with Redux because it makes sense for my app and I don't have any problems there.
Switch from Thunk to Sagas
I started working on my async api calls to populate my app with data. I'm using a lot of data grids and I'm not sure where I'll end up on latency as some of the queries are quite complex.
When I started working on the action creators and methods for doing background polling of data I realized that Sagas were going to be much easier than Thunk.
I made that switch and I'm happy with it. Handling any errors from the api calls is being handled by an action creator that updates redux state container for all of my api calls. Errors are displayed by populating a modal based on those state changes.
Introduciton of Redux-Form
Once I started working on posting form data back to the api things got interesting and I realized I was about to write a lot of code to handle it all through Redux. Redux-form simplified things as it has a state container for everything form related and makes it really easy to setup and validate forms on the client side.
Redux-form handles all of the form state in my configuration until the form is submitted.
I'm using a container component conected to a Redux store I created to hold state of api requests.
The form is a child component of the container that is connected to Redux through redux-form which handles all of it's state.
When the form is submitted I am calling a Redux action which in turn called a saga to post the data.
The result of the saga api call is to either dispatch a success or failure action in Redux. I am passing an object to the api state that contains the status (success/failure), an error object with any errors, and a return object where I can return things like the id's of records just created.
That works well when the error from the api is communication related. Because I'm updating the api state my higher level app components have access to it so I can do things like trigger a modal for errors not specifically related to the form data itself.
But when I started thinking of how I would handle any field errors that could occur if the client side validation was missing some logic I got lost.
In my current setup those errors would be on the api state object. I could put them into a modal but there would be no client side error handling on the form itself.
Redux-form can handle server side validation tied directly back to the form fields but only from a promise and from what I can tell trying to return a promise through action creators would be difficult if not impossible.
I can write a promise in my onSubmit function but I would have to call my saga function directly instead of triggering it through an action. Is that an acceptable pattern?
I guess I could trigger an action from the saga to populate my api state values but it seems backwards.
Basically I would prefer to handle comm errors one way (through my api state container) and form field data errors another way (back throu redux-form and it's error handlers) and I'm not sure which direction to take.
I looked at a module redux-form-saga which makes it possible to return a promise directly back to the form and therefore use the redux-form error handling after the api call but I'm not sure if I would be able to also trigger my api state actions at the same time.
Rather than continuing going down the rabbit hole and maybe over complicating things I thought I would solicit some advice from anyone who has had to deal with something similar.
I'm good with async background calls to populate my data grids but when I have to post data back to the api I want to make sure the user can't take any other actions until they get a response back.
This is the first section of many in this app so I want to create a design pattern that makes sense, is easily reproducible, is reliable, and easy to follow.
Any suggestions?
React-Boilerplate will help you integrate React, redux, redux-saga. On top of that integrating redux-form should be straightforward. React-Boilerplate uses all the current best practices of the community for a production ready app
Building a React application with redux as the flux pattern.
To use an api a token exchange request needs to happen. This has to occur only once when the React application starts. The access_token returned from the token exchange needs to be stored in the redux state and accessible by other api calls.
One approach i tried is by calling a redux action in the App(parent) component, and then all other calls are within children components. New to React i now understand that this is not the right approach as the React components lifecycle events and the actions and reducers called do not follow a synchronous flow, so the redux actions are called asynchronously.
How do i ensure a redux action is called prior to any other redux action that depends on the results of the first redux action? Which middleware would be best suited for ensuring a synchronous approach redux-thunk, redux-look and redux-saga.
If you need a process to run before any other action, you could do it before creating the store, and passing the result in your main reducer function at store creation.
Then, just render the app after the promise or callback of this process is done.
Otherwise, just dispatch this initial action after the store creation, and before app render (with redux-thunk if it is async).
You can use redux-thunk to have a "promise like" behavior when displatching actions. This way you can ensure an action was done before dispatching another one.
In my current ReactJS component, I have to call a REST API and get the JSON. It is done in componentWillMount.
I have introduced Redux in my app. Where should I make the call now to get the JSON and set as the default state? Is it in Redux or my React app?
Any example appreciated.
You'll usually want to dispatch an action from componentDidMount (or Will depending on your lifecycle constraints). That action will kick off the XHR and usually return either a thunk (redux-thunk) or a promise (redux-promise-middleware). If a thunk, it will be set up to dispatch another action with the results, or with a promise it does that for you, then reduce that state in as per normal and bind it to the component.
A common practice is to have a configureStore.js file that exports a configureStore() function that handles the store setup (initial state, middleware, and enhancers) and returns your store. See the "real-world" example in the redux repo for an example of this.
In your case, a simple approach would be to request the data from your REST API when your app starts up, and then when you receive the response, call configureStore(initialState) (where initialState is the data you fetched) and then proceed with the rest of the app setup and initial rendering. This approach will add a little time to your app startup though, because its initialization will be paused while it's waiting for that API response.
Another option would be to just create your store normally (without the prerequisite API fetch), and then make the actual initial state request from your API after your store has been created. When that API response is received, you could dispatch an INITIAL_STATE action, and have reducers ready to handle that. In this approach, you'd probably want some sort of loading indicator in place during this initial fetch, since your app will have rendered or at least started to render during the API request.
If you're doing server rendering, you can just fetch the initial state data from the server side, and attach it to the window object of the index.html that you're rendering. See the "universal" example in the redux repo for an example of this. That'll allow you to simply grab your initial state from the window object when you create your store.