Improving Flux architecture by reducing unnecessary code - javascript

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.

Related

How to handle webhook fulfillment in Dialogflow using nodejs

I am looking for some advice on how to design the code to handle the fulfillment of requests sent by Dialogflow to my server. Dialogflow only lets setup a single webhook to handle all the intents. Let's say that I have 5 different intents; all of them will call the same webhook on my server. Now, how can I elegantly manage server-side different workflows depending on the intent?
The parameter that I would ideally use to make a distinction is contained in req.body.queryResult.intent.displayName; and indicates the name of the current intent. Right now I have two ideas, using express redirect method using the intent as part of the path, or creating a dictionary of handlers where the intents are the key.
Do you have any suggestions?
The dialogflow-fulfillment library, although deprecated, uses your latter approach - creating a Map from Intent name to Handler function and handing this map to a Dispatcher. It is a simple, straightforward, and speedy approach.
The multivocal library takes a similar, tho more expansive, approach, letting you register a handler against either the Intent name or the Action value assigned and having separate configurations for the response based on either Intent, Action, or another value that is set in the handler.
Redirecting to a new, path-based, method does not seem to give you anything.

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.

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

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/).

Server side rendering with async data fetch

We are building our website with react/react-router/redux
We want to server side render our pages that should be filled by the data from our data sources. This transaction has to be asynchronous and unfortunately since we want to server side render, we can not use "componentDidMount" function.
In the redux tutorial page at server side rendering section here, it has been advised to :
If you use something like React Router, you might also want to express
your data fetching dependencies as static fetchData() methods on your
route handler components. They may return async actions, so that your
handleRender function can match the route to the route handler
component classes, dispatch fetchData() result for each of them, and
render only after the Promises have resolved. This way the specific
API calls required for different routes are colocated with the route
handler component definitions. You can also use the same technique on
the client side to prevent the router from switching the page until
its data has been loaded.
This is currently how we handle our data fetch. I personally did not like this approach it looks quite clumsy and it is too coupled to the routing library. Are there any better ways to do it - hopefully with standard react/router/redux components ?
Something like a static fetchData() method is the correct way to handle data fetching with React Router in the general case, though it can reach down into child components as needed (which is e.g. how Relay works).
The reason you want to do it this way is that React Router resolves all the matched routes all at once. Given that, you can then run data fetching for all of your route handlers simultaneously.
If instead you tied data fetching to instance-level handlers on components, you'd always end up with fetch waterfalls, where a component could not fetch its required data until all of its parents receive their required data, and so forth. While that may not be a big problem on the server, it's hugely suboptimal on the client.
If you really want to colocate data dependencies to components, you can consider using something like React Resolver, but this can easily lead to a suboptimal experience for your users.

ExtJS 4.1 - Store.add() (followed by sync) vs Model.save()

FIRST: I realize this question has been asked here: in ExtJS, is it better to call Model.save() or Store.Sync()? - however I wish to examine this further, specifically regarding minimizing XHR's and unnecessary overhead on both the client and server. I do not feel either of these points were addressed in the linked question.
I have a somewhat large application designed for enterprise resource management, consisting of many models, views and controllers. I handle all responses from my server by establishing a listener to Ext.Ajax requestComplete and requestException events. I took this approach rather than writing duplicate event handlers on every model's proxy afterRequest event. This enables me to have all of my back-end (using the Zend Framework) controllers responding with three parameters: success, message and data.
After a successful request (i.e., HTTP 200), the method run for requestComplete will inspect the JSON response for the aforementioned parameters. If success is false, it is expected that there will be an error message contained in message, which is then displayed to the user (e.g. 'There was a problem saving that product. Invalid product name'). If success is true, action is taken depending on the type of request, i.e., Create, Read, Update or Destroy. After a successful create, the new record is added to the appropriate data store, after delete the record is destroyed, and so forth.
I chose to take this approach rather than adding records to a store and calling the store's sync method in order to minimize XHR's and otherwise round trips. My current means of saving/updating data is to send the request to the backend and react to the result on the Ext front end. I do this by populating a model with data and calling model.save() for create/update requests, or model.destroy() to remove the data.
I found that when adding/updating/removing records from a store, then calling store.sync(), I would have to react to server's response in a way that felt awkward. Take for example, deleting a record:
First, remove the record from the store via store.remove()
Invoke store.sync() as I have store's autoSync set to false.
This fires the AJAX destroy request from the store's model proxy.
Here's where it gets weird.... if there is an error on the server while dropping the row from the database, the response will return success: false, however the record will have already been removed from the ExtJS Data Store.
At this point, I can either call store.sync(), store.load() (both requiring a round trip) or get the record from the request and add it back to the store followed by a commitChanges() to avoid calling an additional sync/load and thus avoiding an unnecessary round trip.
The same goes for adding records, if the server fails somewhere while adding data to the database, the record is still in the ExtJS store and must be removed manually to avoid a round trip with store.sync() or store.load().
In order to avoid this whole issue, as I previously explained, I instantiate one of my model objects (e.g. a Product model), populate it with data, and call myModel.save(). This, in turn, invokes the proxy's create or update depending on the ID of the model, and fires the appropriate AJAX request. In the event that the back-end fails, the front-end store is still unchanged. On successful requests (read: success: true, not HTTP 200), I manually add the record to the store and invoke store.commitChanges(true), effectively syncing the store with the database without an additional round trip and avoiding unnecessary overhead. For all requests, the server will respond with the new/modified data as well as a success parameter, and conditionally a message to display on the client.
Am I missing something here, or is this approach a good way to minimize XHR's and server/client overhead? I am happy to provide example code should that be requested, however I feel that this is a rather general concept with fundamental code.
I think you have eloquently argued your position. I don't see anything wrong with the position you have taken. My only reproach is to point out that autoSync setting on a store that backs editable grid is a far less verbose way of accomplishing the task, albeit with less control.
To add, the overhead which you point out is typically due to the unexpected or I would call edge cases that may need special handling or an extra refresh of data. You could add listeners for those specific cases and leave the rest functioning with terse defaults.

Categories

Resources