React.js - flux vs global event bus - javascript

What is the advantage of using Flux over a global event bus? I think the dispatcher is all that is needed:
component publishes 'user event' with data to the dispatcher
dispatcher executes handler of the subscribed store
handler publishes 'update event' with the store's updated properties
dispatcher executes handler of the subscribed component, and updates component state with the store's updated properties
What am I missing here that I can't do without Flux?

I think what others have said about application structure and the change event is important, but I should add this one thing:
The dispatcher's waitFor method is the biggest difference between registering the stores with a dispatcher vs. the stores listening to a global event bus. This method lets you manage which stores update before others. And that becomes vital when you want StoreB to look first at what StoreA did before it decides what to do.
You could think of the dispatcher as a global event bus with a waitFor method, and that would be somewhat accurate.

I'm not an expert in flux but an architecture doesn't enable you to do something that wasn't possible before, it gives your application a structure that is extensible and understandable.

I believe it's all about code structure which is understandable even in large scale.
Supose you have appState which holds underlying data for components.
The components call action. Action is responsible for gather data from XHR or modify the incoming data from component and then it dispatch complete data to subscribed store.
Store is the only part of your code, which can modify your appState and it is basically the only thing, what it does. It takes data from action and store them to appState or removes some data from appState according to action.
Then you fire stateChanged event, which your component should listen to and will rerender.
So you have all action specific logic in actions. You handle appState only in stores. And that should help you keep your code understandable.
Flux pattern
My understanding of why is good idea to dispatch only complete data comes mainly from this article. And it is based on official Facebook Flux diagram
The advantages of this approach are:
stores are simple and synchronous, does not contain decision logic, just handles given data
there is no need to fire another action in store, which will break one-directional chain of Flux
dispatcher is the single channel for all state changes, it knows what action with what data is processed, so its easier for debugging

You basically described flux, the only difference is:
stores emit a change event
And the component updating its state isn't part of flux, that's a common practice for integrating flux and react.
Flux just names each of these pieces and gives guidelines on what each piece's responsibility is.
It's essentially a main event emitter (dispatcher), the event types (actions), functions that emit an event on the dispatcher (action creators; the event body is a payload), and other event emitters that: keep state, listen to the dispatcher and emit change events (stores).
At least that's how it works in JS. The core principle is the unidirectional data flow. There are plenty of event emitters that are used for bidirectional communication.

Related

Angular is Based on Event Driven or Data Driven Model

Angular is based on Event Driven or Data Driven Model.
using of ngRx follows which pattern data driven or event driven.
I think it really depends on your implementation.
If your implementation is based on CRUD, I guess you say it is data driven as any http requests will mutate state data that will eventually trigger UI update.
However, if your overall system is implemented in for example SignalR based architecture, then coming SignalR event shall dispatch ngrx actions with a playload to be able to mutate state. In this case, I guess you can say it is an event driven model.

Where to put non-ui logic in react/redux app?

I'm writing a react/redux app that has a Job object that fires Events from time to time. On these Events the user is expected to react. I can easily write the React component that shows such a job or events, but don't know where to put the logic when
the user is not on the Job page
and an Event happens
and I would like to pop up a notification
Of course, once I get access to the store, I can create the notification too.
Shall I handle such logic in a React container that render() nothing?
Or handle it with vanilla JS when I load a Job data?
Or to handle it in the reducer when the data is stored? (probably not recommended)
My problem with the option two is that I don't know how to access the redux store from a totally ad-hoc code, as my store is not a global object.
What do you recommend?
Generally speaking, the two places that you'd put code that needs to access the store (for either dispatching or receiving state updates) is in middleware or a connected component. If you specifically want to respond to an action coming through, then you would need to use middleware.
I actually threw together a sample timer middleware in a chat discussion a few weeks ago. I just pasted it as a gist here as an example: https://gist.github.com/markerikson/ca96a82d6fdb29388aca4052a9455431 . Illustrates the idea of doing something asynchronously in the background.
You may also want to look through the list of middlewares in my Redux addons catalog: https://github.com/markerikson/redux-ecosystem-links/blob/master/middleware.md . Numerous examples of ways to execute background-ish logic.
Finally, https://github.com/yelouafi/redux-saga (which is itself a middleware) is a fairly common lib used to do background-ish logic.

Flux calling actions with arguments managed in store

Say I have an action someAction(params) that takes params which is managed in a store paramsStore:
paramsStore.listen(function(params) {
someAction(params)
})
It seems that I can't just call this in my view because apparently this goes against the Flux way of doing things (actions shouldn't be called within store listeners).
The reason I have someAction inside the store listener, is because I want it to be called every time the paramsStore is modified. How can I achieved this without resorting to the 'unpattern' of calling actions within stores listener?
The right "flux way" of doing it would be to call the someAction(params) wherever information is dispatched to paramsStore.
Understanding what someAction does will give more clarity. Does it really need to be an action? If you're just doing some manipulation in the store data, you could have it as a local method in the paramStore.
While I am new to flux as well I could offer a suggestion. State that is needed to determine the outcome of an action that is held by Store A could be attached to a get method. This state can be retrieved by a View with a getter. When the action is called this state can be sent as a parameter. If something needs to be async it can now be done here (ajax call or something else) based on what the state is. Either the result of this or a promise object can then be used to trigger an action which is passed to the dispatcher. The dispatcher sends the result or promise to the store. The store then updates its state and the process repeats as necessary (when initial action is triggered).
I think a little more detail of what exactly you need would help actually. I do believe listening for for an action and triggering another action inside the store doesn't coincide with flux. I do think there is likely a way to accomplish the actual result you want using flux but without more detail this is the best I could come up with. Also, in reality you can implement anything you want. Flux is just a model and by extension a self imposed constraint to help with structure.
If you are using Flux as is, you could refer to the original image of the whole architecture at https://github.com/facebook/flux.
As you can see not only views could create actions. There are also Web API Utils which could create ones. Generally speaking not only API utils can do this. It's totally okey to create actions in order to start some behaviour according to outside world, some services or something else.
But in your case you are trying to create an action on some store update listener. As far as I can understand this would result in some changes in one or few other stores. In this case you probably don't need to create an action in the listener, but rather create some relations between your stores with waitFor API. Here is a link with detailed information: http://facebook.github.io/flux/docs/todo-list.html#adding-dependency-management-to-the-dispatcher.

reactjs - input fields rendering in a hierarchy

I am building a simple React application with the following component hierarchy structure:
--- ReqList (shows a list of Request Items)
------ ReqListHeader (A div that has list title and some buttons)
------ ReqTable (list of request items)
--------- ReqRow (one row of request)
------------ ReqItemHeader
------------ ReqItemBody
------------ ...few more components in between
--------------- ReqEditor
------------------ TextArea
The root component receives data via ajax call and calls setState(data), as per the standard docs of React, and all is well, and this works correctly. I am able to show all descendant components and their values.
However for form input (textarea), the input doesn't change. I understand that I have to implement a change handler. The thing that I am unsure about is, where to implement it?
Option I:
I initially thought, I would just add a changeHandler function in its immediate owner, by calling setState() on it. But I am afraid that I am breaking the uni-directional data flow principle by introducing a state in a middle level component.
Option II: Should I pass a changeHandler callback as a property from say "ReqRow" component all the way down to ReqEditor, so that it could be bound to textArea change event?
Option III: Or should I start at the root of the hierarchy i.e. ReqList? That is because, even ReqRow receives the data from its owner and its parent and so on, since that is the entry point for data.
I am not too sure, the level of upwards propagation that I should do in this case. Most of the examples are simple ones with two level hierarchy. I am sure this can be done, but involves passing down the change handler callback all the way from to its grand child.
Is this correct, or is there any other better way?
The problem your facing is solved by using any of the Flux pattern implementations. React only provides a solution for the data rendering part, but it does not provide any clue on how to handle the data flow.
Flux is a pattern proposed by Facebook that tries to structure your app so changes in the data are manageable in a clean way.
From the Flux documentation:
All data flows through the dispatcher as a central hub. Actions are provided to the dispatcher in an action creator method, and most often originate from user interactions with the views. The dispatcher then invokes the callbacks that the stores have registered with it, dispatching actions to all stores. Within their registered callbacks, stores respond to whichever actions are relevant to the state they maintain. The stores then emit a change event to alert the controller-views that a change to the data layer has occurred. Controller-views listen for these events and retrieve data from the stores in an event handler. The controller-views call their own setState() method, causing a re-rendering of themselves and all of their descendants in the component tree.
This dense paragraph is a summary of the solution to your problem.
EDIT: You can also employ baobab, a library that offers an inmutable tree of data that emits events when some field (or its children) are updated. So each component listens to changes on the fields that it needs. There is a package for integrating it with React. I've used it and works great.

a scenario flux doesn't support

I am using flux architecture with React and I have an issue I don't know how to handle.
I need to write a logic that will listen to dispatched action (like a store) and will trigger an action in case the payload contains a specific value.
For example, assume there is an action that dispatch "ITEM_CREATED". My component should catch this "ITEM_CREATED" event and it's payload, and check whether the payload contains correct serial number. In case the serial number is incorrect, my component should execute an action.
Implementing this logic in a store will lead to a-synchronic store, moreover, in flux I can't trigger actions from store.
A possible solution is to create a "virtual" component (with falsy render() method) that will do that logic. Such solution will force me to put this virtual component in my JSX markup, which seams like a hack or a bad workaround.
I really want to know what is the flux solution for such scenario.
Thanks
The answer here is to back up and do everything in response to the original action, not to create a cascade of actions.
See also:
Flux Dispatch.dispatch(...): Cannot dispatch in the middle of a dispatch
Dispatching further actions when handling actions
https://github.com/facebook/flux/issues/133#issuecomment-70775063

Categories

Resources