React/Alt - avoid dispatching within a dispatch when responding to user input? - javascript

I have a component that takes user input. When they save, I use an action to update a store's state
In response to this new information, a results component needs to run an async operation and then respond when new information comes back.
No matter what I try, I seem to be left with a hack setTimeout or a dispatch-within-dispatch error.
The async operation is defined via a datasource and has its own store as outlined here. What's the correct way to structure this behavior?
User input is received by input component.
Input component uses an action to update a store's state
Currently, the store attempts to start the async operation needed by the output component
My choice at this point seems to be Dispatch-with-dispatch error or a hack solution involving setTimeout. Neither feels correct.
What am I missing?

Ignore the examples about DataSources. Do not use registerAsync in stores.
Instead, use actions to perform async behavior and have results update stores. In the example you gave, do this from the input component:
Action1.updateStore()
AsyncAction2.run()
Then, use a store watching AsyncAction2 actions to update and inform result components.

If you're sure that you want to be dispatching at that point and just want to avoid getting the "dispatch within a dispatch" error you can use alt's .defer method (see: http://alt.js.org/docs/actions/).

Related

JAMStack - Small E-commerce store

Building a simple E-commerce store with Nuxt and Prismic.
I have this very simple action in my store:
async GET_ALL_CATEGORIES({commit}) {
// gets all the categories from prismic
// Set categories to the state
}
My question is, when I move around the application from / to /category1 to /category1/product1 should I be dispatching this action everytime?
Would one save this array of categories in localStorage?
Should I have an if block in my asyncData that checks for the categories state and if it is empty, dispatch the action, otherwise use whats in state?
How do the pros handle this situation?
Thank you!
It depends on how often you think your 'categories from prismic' would change. If not very often then you can save it to the store and then just read from the store.
Otherwise you may want to query your API etc on every page load, probably in mounted()
EDIT: You many also want to set an expiry date on the state so that it can pull in fresh data at intervals

Event Listeners blocking input in React

I'm rendering a react component that sends a request on render (as well as when state changes), but also receives user input.
I'm adding an event listener to accept user input, however, it seems like the events are being blocked by the request being sent. Here's a code snippet of what I'm doing. In the body of the component, I return a simple <Loading/> indicator when the request is happening.
To summarize what happens, when the component mounts, I'm unable to capture user input until the request finishes. Further, on subsequent changes to user input, the input is blocked by the request.
Any thoughts here? Or advice on how to debug?
#Jaromanda X was correct in the thread above. In the render of my function component, when parsing the returned data (something like data.map()), I was making expensive cpu-bound calls. Pagination or caching the data will do the trick.
In functional components, you can think function body as the render() method of old class components. So, when you try to send api request in there, it blocks the rendering of the element. You should make api call in an useEffect() function. So, it will work after component mounted without blocking it.

Intercepting Actions in React Components

I have a React application that uses Redux.
The application displays the results of some calculations at the top and some of the constituents that go into those calculations at the bottom. The user can click a button which pops up a modal in which the user can add one of these constituents. This will fire off an action during which it will send that new constituent to the backend, which will make those calculations have different results.
As you might expect, what I want is to refresh those results from the server based on the new data. The calculations are quite complex so replicating the calculation in the UI is not an option.
There is a loadConstituents() method which is called by componentWillMount() when the user lands on the page. I basically need to call this method again once the server confirms to the user that the data was received (via a SAVE_SUCCESS action).
How can I intercept an action in my component?
Alternatively, is there a better pattern for achieving this?
The best thing I could think of is passing the loadConstituents() function to the modal, which would pass it to the call, which will execute it once the call is done but passing a function through so many classes as a parameter seems very hacky.

Should I store promises in Redux?

I'm using Redux and React in an online food-ordering app.
When the user removes an item from their basket, I need to fire off an XHR request to the server to compute the new total price for the basket. When this XHR completes, I update the redux store and render the new price. I'm using Redux thunk to manage this async operation.
There is a problem is a user removes two items from the basket in quick succession. The user removes the first item, and I fire off an XHR to get the new price. Then the user clicks a button to remove a second item, and a second XHR is fired off.
The UI will be in an incorrect state if the second XHR completes before the first - the price of the basket with only the first item removed will be shown.
To work around this, I want to cancel the first (in-flight) XHR when the user clicks the button to remove the second item. To cancel the first XHR I need to keep track of the promise object (I'm using axios to manage XHR).
It makes sense to me to store the in-flight XHR in the redux store. Is it bad practice to store promises in Redux like this? It seems to be frowned upon - Redux should really just be storing plain data.
This is covered in the Redux FAQ, at http://redux.js.org/docs/faq/OrganizingState.html#organizing-state-non-serializable :
It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.
Generally, any async behavior like this is handled externally to the Redux store, via promises or middleware like redux-thunk, redux-saga, or redux-observable. For some comparisons between these approaches, see the recent articles Redux 4 Ways and 3 Common Approaches to Side-Effects in Redux.

Improving Flux architecture by reducing unnecessary code

In our codebase, we have recently migrated a lot of React components to a pure flux architecture. Thus, our data flow looks almost exactly like this image provided by the Facebook team:
(source: github.io)
One issue we're running into is that there's a lot of boilerplate code required to make a call to the server and get a result. The process is as follows:
View propagates an action called something like GET_DATA_FROM_SERVER to an action creator (let's say called ViewActionCreator).
ViewActionCreator dispatches this action, which has no payload in most cases, and then calls api.retrieveData
Upon receiving data from the server, api.retrieveData dispatches an action, in this case called SERVER_DATA_RECEIVED with the retrieved data as the payload.
Stores respond to the two actions dispatched. However, in most cases stores only do something for the second action (SERVER_DATA_RECEIVED), since we've found that optimistic view updates are, with a few exceptions like logging in, not usually required or very helpful.
Hence, my question is, is there any reason why we shouldn't have views call api's methods directly, and have those api methods dispatch actions only upon data reception?
Another related issue we're running into results from the use of constants, generated using https://github.com/STRML/keyMirror. We repeatedly run into an error where we forget to add a constant used in an action creator and store to our constants file, but this doesn't manifest until runtime, since our stores use switch statements to test which action they're receiving from the dispatcher, and when we use a constant that's undefined, this simply percolates down to the end of the switch statement.

Categories

Resources