How to deal with hierarchical data with Reflux stores? - reactjs

Outline
In my app I'm using React and Reflux and have a hierarchical setup with regards to my data. I'm trying to break elements of my app into separate stores to be able to hook events correctly and separate concerns.
I have the following data flow:
Workspaces -> Placeholders -> Elements
In this scenario, when a workspace is created a default placeholder must in turn be created with a reference (ID) to the newly created workspace. The same applies for the placeholder to element relationship.
Sticking point
The Reflux way seems to suggest the PlaceholderStore listens to the triggers from WorkspaceStore, adding the newly created ID to this.trigger().
Reflux only allows a single event to be triggered from stores; thus preventing external components being able to discern create or update actions. This means that if one trigger in the store sends an ID as argument[0], subsequent triggers should do the same (to remain consistent). This is a problem for components looking for updates to multiple workspaces (e.g. re-ordering / mass updates).
Undesirable solution
I had thought to add in a concept of StoreActions; Actions that only stores can create, that other stores would then listen to (effectively discarding the original trigger from stores). With this components / stores could listen to specific events, and the arguments passed to said events could be tailored without worry. This seems like a wrong way to go and an abuse of the Reflux event system.
Help
Should I be trying to break up related data? Is there a better way to structure the data instead?
I've read about aggregate stores, but not seen any implementations to dissect. Do these offer a solution by way of bringing data from multiple stores together, and if so, what is responsible for creating events React components can listen to?
Many thanks for any help / insight anyone can offer!

Yes, it is perfectly reasonable to call actions from a store. I see actions as initiators of data flows and I consider exceptional flows as seperate ones.
A good example is a CRUD store that also handles AJAX calls (to CRUD the data with server-side). The store will trigger the change event as soon as it's data gets updated. However in the event that an AJAX call fails, it should instead start a data flow for that instead so that other stores and components can listen in on those. From the top of my head such errors are in the interest of a toast/notification component and Analytics error logging such as GA Exceptions.
The AJAX example may also be implemented through the preEmit hook in the actions and there are several examples among the github issues discussion on that. There is even this "async actions" helper.
It's by design that the stores only emit a change event. If you want to emit other kinds of events, it basically means you're starting new data flows for which you should be using actions instead.

Related

Example of using Redux with vanilla, controlled form components in React?

I'm new to Redux, but not to React. And I'm having trouble envisioning how to architect this.
My app has a complex, nested data structure—a "record." A single-page form lets users edit all the fields for that record. Edits are not simple: I need to check whether certain fields are different between the old record and any new edits, upon the user's submission of the form. If there are differences, I need to perform a bunch of fancy logic to update the record properly. (For example, edits the user made to a single field may need to be propagated to various deep parts of the record, a list of derived data needs to be re-generated and stored in the record, etc. etc.)
I want to:
Use Redux as the record store. (I got this part.)
Hydrate my form component with a single record from the store.
Use vanilla React to store form field state (i.e. ordinary controlled form elements)
On submit, compare the old record (i.e. from the store) with the new record (my component's state), perform fancy logic, and then update the store with the record.
I don't want to install other libraries, besides Redux or Immutability Helper. So, no Redux-Forms or other business.
What's the best way to architect this? I have the basic architecture down. That is, I have got a Redux store working and can do simple updates (like pushing new data to an array, or replacing an entire record). But I don't know how to organize my "fancy logic" and where to do the fancy logic I need. For example, should this logic:
Be handled by my form component, before dispatching a neat object to be stored in the Redux store?
Be in an external utility library, and called by the action creator?
...be in an external utility library, and called in the reducer?
...be handled directly in the action creator or reducer, all dozens of lines of logic?
Thankful in advance for pointers to examples of mixing plain vanilla React forms with Redux, and tips on how to architect this.
My "Practical Redux" tutorial series has three posts that cover exactly this kind of behavior:
Practical Redux, Part 6: Connected Lists, Forms, and Performance
Practical Redux, Part 7: Form Change Handling, Data Editing, and Feature Reducers
Practical Redux, Part 8: Form Draft Data Management
The approach I demonstrate is to copy the item being edited to a "draft data" section of the Redux store, have all form change updates apply to that draft version, and then have reducer logic to overwrite the original version with the changes when the user saves the updated form. You could certainly have variations on that if you want, including keeping the draft data in component state instead.
In general, I personally would try to move most of the actual logic outside of the components, as most of that should be independent of the components themselves. Jack Franklin has a recent article on extracting logic from React components that's a good example of that mindset.
Also, note that you may want to consider using selector functions to derive data, rather than explicitly putting it all in the store.

Angular 2 architecture for server-side communication

Learning Angular 2. What would a recommended file structure for having components communicating with a server?
So a feature, say a todo feature. It may have a main todo-component, a todo-list-component, a todo-item-component, new-todo-component and a todo-service (and probably more).
Then there is another feature, say a personal activity timeline, which takes several source (including new and finished todos) and present it to the user. Say it may have the same type of files, but so different that we could not combine them into generic ones: a main timeline-component, a timeline-list-component, a timeline-item-component and a timeline-service.
Then we want for both the todo and the timeline features to communicate with the server. Since they both access partly the same data, perhaps a good idea would to have a backend-service to take care of the server communication for both features.
But how should the components get the data it's need? Should the todo components ask the todo-service which in turn asks the backend-service (and similar for the timeline components)? Or should the components better use the backend-service directly, so for example the todo components would use backend-service for backend stuff and todo-service and for other things that is naturally to put in a service? Since this is async and there are observables involved (which in the first case would need to be sent over multiple "steps" somehow), perhaps the latter is a simpler/cleaner approach?
Ideally the Component should use a proper Service to pipe itself into the data flow with Observables.
If we look for instance at the Chat application example we can see that each Service has a clear responsibility for the data management.
I wouldn't allow a Component to access a generic Http service as it would need to host too much logic to communicate with the server: the component doesn't care about the data source, just shows the data.

The "flux" way to handle action success/error in UI

Take the case of reseting a password. The user is presented with a form asking them to enter their email. They submit the form so that they'll be sent a reset link in an email. The submit triggers an action, the action makes a POST to /api/password/reset and will return success or failure.
Obviously i want to update the UI so the user knows what is going on. The Flux way is to have actions dispatch a constant e.g. PASSWORD_RESET_SUCCESS and stores listen to the dispatcher so they can change the state. Components listen to the stores so they change the UI when the store state changes.
In the case of the password reset, i can't really see a sensible way to have this run through a store (and it seems verbose to do so). The only changing of state seems to be directly related to that form/component. Nothing that needs to be preserved once the user has left that page.
Is it "flux-y" to have components listen directly to the dispatcher?
Is there a sensible design for a store that allows me to handle generic events like this that don't directly link to models in the app?
Many thanks!
(This relates to working on https://github.com/mwillmott/techbikers in case anyone is interested)
No, it isn't. The architecture of the Flux should always follow the same scenario — Component calls actionCreator, ActionCreator dispatches actions to the stores, store emits change to all subscribed components. That is how Flux works, explained here.
I think the best way to do it is to have the general ResultStore, which simply accepts key/value defined in the action and writes them to hash. This way you can get away with one handler, with the name onResultWrite or something like this. Flux Stores were never meant to be a direct representation of your models — they are more a representation of your whole app state.
Flux architecture obviously can seem too strict and complex for the simple app — and it is. But it was not designed for simple apps in mind, it was designed for the complicated UI with lots of components — as complicated as the get. That's why stores, actions and components need to be separated from themselves as much as possible.
If you think that your application is quite simple, you can always take shortcuts, like passing a changeState callback directly to the action as a param — but if some other component will need to react to the PASSWORD_RESET_SUCCESS event, you've got yourself a problem. You can always think about it when it happens though. The project architecture is always about trade-offs, flexibility vs development speed vs performance.
The most important skill of developer is to know about this trade-offs, their value and know where to make them — and where not.
Good luck!

Should we store "temporary" info in React/Fluxible stores for an isomorphic app?

At our studio, we're struggling with understanding good usages of stores in react/fluxible. Essentially, how do we store temporary information (like success and errors) required to proceed through UI flows without keeping that information around forever? We have always understood stores as keeping persistent information. In a multi-page registration flow, step1Complete doesn't seem like a good candidate to track in a store.
Another option we've seen is to use AJAX calls in the component to make these simple calls that just grant you the data you need in the moment in order to proceed. Is that a common practice? Does that break an isomorphic app?
Are we overthinking?
success for a step can also be classified as a state of the step, is it not? I would keep it as a prop for the step.
Or as #Cory pointed out, router2->Action-> store update->emit change->step 2
with great power comes great responsibility.Dont use ajax calls for boolean state values

Om but in javascript

I'm getting to be a fan of David Nolen's Om library.
I want to build a not-too-big web app in our team, but I cannot really convince my teammates to switch to ClojureScript.
Is there a way I can use the principles used in om but building the app in JavaScript?
I'm thinking something like:
immutable-js or mori for immutable data structures
js-csp for CSP
just a normal javascript object for the app-state atom
immutable-js for cursors
something for keeping track of the app-state and sending notification base on cursors
I'm struggling with number 5 above.
Has anybody ventured into this territory or has any suggestions? Maybe someone has tried building a react.js app using immutable-js?
Edit July 2015: currently the most promising framework based on immutability is Redux! take a look! It does not use cursors like Om (neither Om Next does not use cursors).
Cursors are not really scalable, despite using CQRS principles described below, it still creates too much boilerplate in components, that is hard to maintain, and add friction when you want to move components around in an existing app.
Also, it's not clear for many devs on when to use and not use cursors, and I see devs using cursors in place they should not be used, making the components less reusable that components taking simple props.
Redux uses connect(), and clearly explains when to use it (container components), and when not to (stateless/reusable components). It solves the boilerplate problem of passing down cursors down the tree, and performs greatly without too much compromises.
I've written about drawbacks of not using connect() here
Despite not using cursors anymore, most parts of my answer remains valid IMHO
I have done it myself in our startup internal framework atom-react
Some alternatives in JS are Morearty, React-cursors, Omniscient or Baobab
At that time there was no immutable-js yet and I didn't do the migration, still using plain JS objects (frozen).
I don't think using a persistent data structures lib is really required unless you have very large lists that you modify/copy often. You could use these projects when you notice performance problems as an optimization but it does not seem to be required to implement the Om's concepts to leverage shouldComponentUpdate. One thing that can be interesting is the part of immutable-js about batching mutations. But anyway I still think it's optimization and is not a core prerequisite to have very decent performances with React using Om's concepts.
You can find our opensource code here:
It has the concept of a Clojurescript Atom which is a swappable reference to an immutable object (frozen with DeepFreeze). It also has the concept of transaction, in case you want multiple parts of the state to be updated atomically. And you can listen to the Atom changes (end of transaction) to trigger the React rendering.
It has the concept of cursor, like in Om (like a functional lens). It permits for components to be able to render the state, but also modify it easily. This is handy for forms as you can link to cursors directly for 2-way data binding:
<input type="text" valueLink={this.linkCursor(myCursor)}/>
It has the concept of pure render, optimized out of the box, like in Om
Differences with Om:
No local state (this.setState(o) forbidden)
In Atom-React components, you can't have a local component state. All the state is stored outside of React. Unless you have integration needs of existing Js libraries (you can still use regular React classes), you store all the state in the Atom (even for async/loading values) and the whole app rerenders itself from the main React component. React is then just a templating engine, very efficient, that transform a JSON state into DOM. I find this very handy because I can log the current Atom state on every render, and then debugging the rendering code is so easy. Thanks to out of the box shouldComponentUpdate it is fast enough, that I can even rerender the full app whenever a user press a new keyboard key on a text input, or hover a button with a mouse. Even on a mobile phone!
Opinionated way to manage state (inspired by CQRS/EventSourcing and Flux)
Atom-React have a very opinionated way to manage the state inspired by Flux and CQRS. Once you have all your state outside of React, and you have an efficient way to transform that JSON state to DOM, you will find out that the remaining difficulty is to manage your JSON state.
Some of these difficulties encountered are:
How to handle asynchronous values
How to handle visual effects requiring DOM changes (mouse hover or focus for exemple)
How to organise your state so that it scales on a large team
Where to fire the ajax requests.
So I end up with the notion of Store, inspired by the Facebook Flux architecture.
The point is that I really dislike the fact that a Flux store can actually depend on another, requiring to orchestrate actions through a complex dispatcher. And you end up having to understand the state of multiple stores to be able to render them.
In Atom-React, the Store is just a "reserved namespace" inside the state hold by the Atom.
So I prefer all stores to be updated from an event stream of what happened in the application. Each store is independant, and does not access the data of other stores (exactly like in a CQRS architecture, where components receive exactly the same events, are hosted in different machines, and manage their own state like they want to). This makes it easier to maintain as when you are developping a new component you just have to understand only the state of one store. This somehow leads to data duplication because now multiple stores may have to keep the same data in some cases (for exemple, on a SPA, it is probable you want the current user id in many places of your app). But if 2 stores put the same object in their state (coming from an event) this actually does not consume any additional data as this is still 1 object, referenced twice in the 2 different stores.
To understand the reasons behind this choice, you can read blog posts of CQRS leader Udi Dahan,The Fallacy Of ReUse and others about Autonomous Components.
So, a store is just a piece of code that receive events and updates its namespaced state in the Atom.
This moves the complexity of state management to another layer. Now the hardest is to define with precision which are your application events.
Note that this project is still very unstable and undocumented/not well tested. But we already use it here with great success. If you want to discuss about it or contribute, you can reach me on IRC: Sebastien-L in #reactjs.
This is what it feels to develop a SPA with this framework. Everytime it is rendered, with debug mode, you have:
The time it took to transform the JSON to Virtual DOM and apply it to the real DOM.
The state logged to help you debug your app
Wasted time thanks to React.addons.Perf
A path diff compared to previous state to easily know what has changed
Check this screenshot:
Some advantages that this kind of framework can bring that I have not explored so much yet:
You really have undo/redo built in (this worked out of the box in my real production app, not just a TodoMVC). However IMHO most of actions in many apps are actually producing side effects on a server, so it does not always make sens to reverse the UI to a previous state, as the previous state would be stale
You can record state snapshots, and load them in another browser. CircleCI has shown this in action on this video
You can record "videos" of user sessions in JSON format, send them to your backend server for debug or replay the video. You can live stream a user session to another browser for user assistance (or spying to check live UX behavior of your users). Sending states can be quite expensive but probably formats like Avro can help. Or if your app event stream is serializable you can simply stream those events. I already implemented that easily in the framework and it works in my production app (just for fun, it does not transmit anything to the backend yet)
Time traveling debugging ca be made possible like in ELM
I've made a video of the "record user session in JSON" feature for those interested.
You can have Om like app state without yet another React wrapper and with pure Flux - check it here https://github.com/steida/este That's my very complete React starter kit.

Resources