I have a react app where I'm using alt for the flux architecture side of things.
I have a situation where I have two stores which are fed by ajax calls in their corresponding actions.
Having read the alt getting started page on data dependencies it mentions dependencies between stores using waitFor - http://alt.js.org/guide/wait-for/ but I don't see a way to use this kind of approach if one of my store actions is dependent on another store action (both of which are async).
If I was doing this inside a single action handler, I might return or chain some promises but I'm not sure how to implement this across action handlers. Has anyone achieved this? or am I going about my usage of ajax in react the wrong way?
EDIT: More detail.
In my example I have a list of nodes defined in a local json config file, my node-store makes an ajax request to get the node detail.
Once it's complete, a different component (with a different action handler and store) wants to use the node collection to make an ajax query to different endpoints a node may expose.
The nodes are re-used across many different components so I don't want to roll their functionality into several different stores/action handlers if possible.
Related
I'm trying to figure out what is the best way to handle a quite commons situation in medium complex apps using Flux architecture, how to retrieve data from the server when the models that compose the data have dependencies between them. For example:
An shop web app, has the following models:
Carts (the user can have multiple carts)
Vendors
Products
For each of the models there is an Store associated (CartsStore, VendorsStore, ProductsStore).
Assuming there are too many products and vendors to keep them always loaded, my problem comes when I want to show the list of carts.
I have a hierarchy of React.js components:
CartList.jsx
Cart.jsx
CartItem.jsx
The CartList component is the one who retrieves all the data from the Stores and creates the list of Cart components passing the specific dependencies for each of them. (Carts, Vendors, Products)
Now, if I knew beforehand which products and vendors I needed I would just launch all three requests to the server and use waitFor in the Stores to synch the data if needed. The problem is that until I get the carts and I don't know which vendors or products I need to request to the server.
My current solution is to handle this in the CartList component, in getState I get the Carts, Vendors and Products from each of the Stores, and on _onChange I do the whole flow:
This works for now, but there a few things I don't like:
1) The flow seems a bit brittle to me, specially because the component is listening to 3 stores but there is only entry point to trigger "something has changed in the data event", so I'm not able to distinguish what exactly has changed and react properly.
2) When the component is triggering some of the nested dependencies, it cannot create any action, because is in the _onChange method, which is considering as still handling the previous action. Flux doesn't like that and triggers an "Cannot dispatch in the middle of a dispatch.", which means that I cannot trigger any action until the whole process is finished.
3) Because of the only entry point is quite tricky to react to errors.
So, an alternative solution I'm thinking about is to have the "model composition" logic in the call to the API, having a wrapper model (CartList) that contains all 3 models needed, and storing that on a Store, which would only be notified when the whole object is assembled. The problem with that is to react to changes in one of the sub models coming from outside.
Has anyone figured out a nice way to handle data composition situations?
Not sure if it's possible in your application, or the right way, but I had a similar scenario and we ended up doing a pseudo implementation of Relay/GraphQL that basically gives you the whole tree on each request. If there's lots of data, it can be hard, but we just figured out the dependencies etc on the server side, and then returned it in a nice hierarchical format so the React components had everything they needed up to the level where the call came from.
Like I said, depending on details this might not be feasible, but we found it a lot easier to sort out these dependencies server-side with stuff like SQL/Java available rather than, like you mentioned, making lots of async calls and messing with the stores.
I'm trying to understand Flux pattern.
I believe that in any good design the app should consist of relatively independent and universal (and thus reusable) components glued together by specific application logic.
In Flux there are domain-specific Stores encapsulating data and domain logic. These could be possibly reused in another application for the same domain.
I assume there should also be application-specific Store(s) holding app state and logic. This is the glue.
Now, I try to apply this to imaginary "GPS Tracker" app:
...
When a user clicks [Stop Tracking] button, corresponding ViewController raises STOP_CLICK.
AppState.on(STOP_CLICK):
dispatch(STOP_GEOLOCATION)
dispatch(STOP_TRACKING)
GeolocationService.on(STOP_GEOLOCATION):
stopGPS(); this.on = false; emit('change')
TrackStore.on(STOP_TRACKING):
saveTrack(); calcStatistics(); this.tracking = false; emit('change')
dispatch(START_UPLOAD)
So, I've got an event snowball.
It is said that in Flux one Action should not raise another.
But I do not understand how this could be done.
I think user actions can't go directly to domain Stores as these should be UI-agnostic.
Rather, AppState (or wherever the app logic lives) should translate user actions into domain actions.
How to redesign this the Flux way?
Where should application logic go?
Is that correct to try to keep domain Stores independent of the app logic?
Where is the place for "services"?
Thank you.
All of the application logic should live in the stores. They decide how they should respond to a particular action, if at all.
Stores have no setters. The only way into the stores is via a dispatched action, through the callback the store registered with the dispatcher.
Actions are not setters. Try not to think of them as such. Actions should simply report on something that happened in the real world: the user interacted with the UI in a certain way, the server responded in a certain way, etc.
This looks a lot like setter-thinking to me:
dispatch(STOP_GEOLOCATION)
dispatch(STOP_TRACKING)
Instead, dispatch the thing that actually happened: STOP_TRACKING_BUTTON_CLICKED (or TRACKING_STOPPED, if you want to be UI-agnostic). And then let the stores figure out what to do about it. All the stores will receive that action, and they can all respond to it, if needed. The code you have responding to two different actions should be responding to the same action.
Often, when we find that we want dispatch within a dispatch, we simply need to back up to the original thing that happened and make the entire application respond to that.
Morning,
I'm using the SimpleEvent bus to send data from my centralized data reviver to the Widgets. This works really fine, I get one set of new Data form the server, the success method of the RPC call puts it on the Eventbus, each widget looks if the data is for it, if yes it 'displays' it, if not, it does nothing.There is only one data set per request and the widgets don't depend on other data being already sent.
Now I have a Tree widget. The child nodes of the Tree are created throw this data sets too, and this child nodes register itself to the Eventbus to revive the data for their child nodes. The data shall be received in on rush (for performance reasons obv), so I will get multiple data sets which are put on the Eventbus at the 'same time' (in a for loop). I only control the order in which they are put there (first the root, then the data for the first child......). How does the Eventbus now proceeds the events?
Does he wait till the first event is completed, so the first child of
the tree already finished creation and register itself to the
Eventbus, to revive the data to create it's child's.
Does he handle them simultaneous, so a widget isn't even registered to the Eventbus.
Does he mix up the order?!?!
Current solution approaches:
The best solution I can think of, is to only put new events on the
Eventbus when the previous got completed. However I found a method
which does so, or if it is the standard behavior of the Eventbus .
Fire a request processing finished event, when a event was processed by a widget. Yucks... this leads to a lot of additional code and causes big problems, when data is put on the Eventbus which doesn't belong to any widget....
Register a static variable which is set to true when the request got handled and the Eventbus waits this long till he puts the next request on the Eventbus (Quiet similar to two, but way worse coding style and the same problems)
All events are handled by the root tree element, which sends them upwards to the respective child's.
Which solution would you prefer and why?
Regards,
Stefan
PS: my favorite answer would be that 1. is the standard behavior of the Eventbus^^
PPS: The solution should also be working on when introducing Webworkers.
The EventBus#fireEvent is synchronous. It's by design. You can pass an event to the bus, have handlers possibly modify it, and when execution returns to your method you can check the event; this is used for PlaceChangeRequestEvent and its setMessage for instance.
FYI, if a handler throws an exception, it won't prevent other handlers from being executed. The fireEvent will then wrap the exceptions (plural; several handlers can throw) in an UmbrellaException.
Although EventBus is a nice way of de-coupling parts of your application it doesn't mean it should be "overused".
I also think you should be careful not to circumvent the asynchronous behavior of your client-side code by introducing synchronous/blocking like behavior.
Javascript is single threaded so I don't think you can have two events at the same time. They will be executed one after the other.
If you fire an event on the EventBus (i.e. SimpleEventBus) it will just iterator through the list of attached handlers and execute them. If no handler is attached nothing happens.
I personally would prefer the 4th. approach especially if you plan to use a CellTree some time in the future. The Tree widget/CellTree widget handles the event and constructs its structure by traversing through the object.
When a screen has multiple interacting Ajax controls and you want to control the visibility of components to react to these controls (so that you only display what makes sense in any given situation), calling target.addComponent() manually on everything you want to update is getting cumbersome and isn't very maintainable.
Eventually the web of onClick and onUpdate callbacks can reach a point where adding a new component to the screen is getting much harder than it's supposed to be.
What are the commonly used strategies (or even libraries if such a thing exists) to avoid this build-up of complexity?
Update: Thank you for your answers, I found all of them very useful, but I can only accept one. Sorry.
In Wicket 1.5 there is an event bus. Each component has onEvent(Object payload) method. With component.send() you can broadcast events and each component can check the payload (e.g. UserJoinedEvent object) and decide whether it wants to participate in the current Ajax response. See http://www.wicket-library.com/wicket-examples/events/ for a simple demo.
You could add structural components such as WebMarkupContainers, when you add this to the AjaxTarget everything contained in it will also get updated. This allows you to update groups of components in a single line.
When I'm creating components for a page I tend to add them to component arrays:
Component[] pageComponents = {
new TextField<String>("Field1"),
new TextField<String>("Field2"),
new TextField<String>("Field3")
}
As of Wicket 1.5 the add functions take array parameters [1]. Therefore elements can be added to the page or target like this:
add(pageComponents);
target.add(pageComponents);
Components can then be grouped based on which you want to refresh together.
[1] http://www.jarvana.com/jarvana/view/org/apache/wicket/wicket/1.5-M3/wicket-1.5-M3-javadoc.jar!/org/apache/wicket/ajax/AjaxRequestTarget.html
Well, of how many components do we speak here? Ten? Twenty? Hundreds?
For up to twenty or about this you can have a state controller which controls which components should be shown. This controller sets the visible field of a components model and you do always add all components to your requests which are handled by the controller. The components ajax events you simply redirect to the controller handle method.
For really large numbers of components which have a too heavy payload for a good performance you could use javascript libraries like jQuery to do the show and hide things by the client.
I currently use some sort of modified Observer-Pattern to simulate an event-bus in Wicket 1.4.
My Pages act as an observable observer since my components don't know each other and are reused in different combinations across multiple pages. Whenever one component receives an Ajax-event that could affect other components as well, it calls a method on it's page with an event-object and the ajax-target. The page calls a similar method on all components which have registered themselves for this kind of event and each component can decide, on the base of the supplied event-object if and how it has to react and can attach itself to the target.
The same can be archived by using the wicket visitor. I don't know which one is better, but I think that's mainly a matter of taste.
Background
I'm working on a web application utilizing AJAX to fetch content/data and what have you - nothing out of the ordinary.
On the server-side certain events can happen that the client-side JavaScript framework needs to be notified about and vice versa. These events are not always related to the users immediate actions. It is not an option to wait for the next page refresh to include them in the document or to stick them in some hidden fields because the user might never submit a form.
Right now it is design in such a way that events to and from the server are riding a long with the users requests. For instance if the user clicks a 'view details' link this would fire a request to the server to fetch some HTML or JSON with details about the clicked item. Along with this request or rather the response, a server-side (invoked) event will return with the content.
Question/issue 1:
I'm unsure how to control the queue of events going to the server. They can ride along with user invoked events, but what if these does not occur, the events will get lost. I imagine having a timer setup up to send these events to the server in the case the user does not perform some action. What do you think?
Question/issue 2:
With regards to the responds, some being requested as HTML some as JSON it is a bit tricky as I would have to somehow wrap al this data for allow for both formalized (and unrelated) events and perhaps HTML content, depending on the request, to return to the client. Any suggestions? anything I should be away about, for instance returning HTML content wrapped in a JSON bundle?
Update:
Do you know of any framework that uses an approach like this, that I can look at for inspiration (that is a framework that wraps events/requests in a package along with data)?
I am tackling a similar problem to yours at the moment. On your first question, I was thinking of implementing some sort of timer on the client side that makes an asycnhronous call for the content on expiry.
On your second question, I normaly just return JSON representing the data I need, and then present it by manipulating the Document model. I prefer to keep things consistent.
As for best practices, I cant say for sure that what I am doing is or complies to any best practice, but it works for our present requirement.
You might want to also consider the performance impact of having multiple clients making asynchrounous calls to your web server at regular intervals.