Redux: Atomic Flux with Hot Reloading
github.com
github.com
However, I think it's time we stop calling everything Flux. Just because an architecture is unidirectional doesn't mean it's Flux. Facebook described it clearly as an architecture structured with: Dispatcher, Stores, Actions, Action Creators, and Components (sometimes even with the distinction of View and Controller View). Redux is Flux-inspired, but has significant differences. Maybe we should call it just Flux-inspired architecture. The distinction is important because there are other unidirectional data flow architectures such as in Elm (https://github.com/evancz/elm-architecture-tutorial) and Cycle.js (http://cycle.js.org). We might be creating confusion when mentioning "Flux" and meaning different things.
I've been using capitalization to denote the difference, just like Agile vs agile: Facebook's Flux or an implementation of the Flux architecture, versus a flux architecture.
I've read Michael Jackson's article and I didn't interpret it as saying that people using the term isomorphic are outright wrong. Some people are making this assertion and that is what I am trying to refute here.
I disagree with Michael's statement that two things that are the same cannot be isomorphic. The very definition he cites does not exclude the possibly of those things being the same!
"Corresponding or in similar form or relations"
(Even in mathematics the identity function is an isomorphism, it follows from its definition. However, we are not trying to prove a mathematical property here.)But even then the assertion that the server and client side are exactly identical is not correct. Typically such code bases will have slightly different entry points for server and client. Additionally, React 0.14 beta is now splitting the DOM and String renders.
For some 'Universal' is attractive, because they want to use Javascript everywhere. I get that. If you like that, please go ahead and call it 'Universal'.
However, what matters equally is having an abstraction which allows pure functions to declaratively describe the form of components based on immutable data, no matter what the computational model of the target. It is arguably the abstraction that is the isomorphism and code that uses it could be called isomorphic. That could be stretching the term as per the above definition, but that doesn't mean that people who use it are wrong.
I think React provides the necessary abstraction. I have total respect for what the React core team and the community have achieved. I understand that Michael Jackson and Ryan Florence are motivated by wanting to get more people using React. This is a very good thing.
However, other people may be more interested in promoting the ideas behind React rather than React or Javascript specifically. It is these people I am trying to defend.
Grammatically, it’s kind of like the word "similar". I would feel silly saying "JavaScript is a similar language", and I feel equally silly saying "JavaScript is an isomorphic language". Similar/isomorphic to what?
BTW vjeux, great job at React Europe!
It's unlikely that you will choose a flux lib that will be the make or break point of your application.
Even if a library stops being "maintained", most decent flux incarnations are really small (~100 LoC) - it's unlikely that there's some fatal flaw you'll be stuck with.
In summary: redux is neat, but don't beat yourself up over choosing the perfect flux lib - just grab one that you like the look of and move on with building your application.
Docs are incomplete:
Here's an example of the “getters” concept with Redux: https://github.com/faassen/reselect. (Sorry, no README yet :-( ). They don't have to be inside the core.
It's not "Pure" Flux, which is the reason I like it, it doesn't deal with a Dispatcher and it has syntactic sugar for 'common' use-cases, most Rails dev enjoy stuff like that.
Seems like Reflux can't have hot-reloading because there is no (public?) dispatcher to replay values :-/
Ran across a good writeup here: https://www.reddit.com/r/javascript/comments/3ap0y6/flux_no_...
There is no 100% correct way to build complex single page web apps but there is definitely a wrong way and that way looks increasing like progressive enhancement sadly...
I am currently in the early stages of starting a project and I want to use react+flux. However with the different variants of flux finding the one that is the best fit and is going to be maintained a year from now isn't an easy task. I think I might end up using the facebook variant as I'm fairly certain that they will continue to maintain it.
For the reader. This starts to grow quite quickly.
import SearchActions from './actions/searchActions.js';
import VideoActions from './actions/videoActions.js';
import VideoMetaActions from './actions/videoMetaActions.js';
import MusicPlayerActions from './actions/musicPlayerActions.js';
import SearchStore from './stores/searchStore.js';
import VideoStore from './stores/videoStore.js';
import VideoMetaStore from './stores/videoMetaStore.js';
import MusicPlayerStore from './stores/musicPlayerStore.js';
class Flux extends Flummox {
constructor() {
super();
this.createActions('search', SearchActions);
this.createStore('search', SearchStore, this);
this.createActions('video', VideoActions);
this.createStore('video', VideoStore, this);
this.createActions('videoMeta', VideoMetaActions);
this.createStore('videoMeta', VideoMetaStore, this);
this.createActions('musicPlayer', MusicPlayerActions);
this.createStore('musicPlayer', MusicPlayerStore, this);
}
}
What is more, store registration could be improved as well const videoMetaActions = flux.getActions('videoMeta');
this.register(videoMetaActions.setAudioVolume, this.handleAudioVolume);
this.register(videoMetaActions.setMusicVolume, this.handleMusicVolume);
this.register(videoMetaActions.setMusicUrl, this.handleMusicUrl);Let me first explain Flux in five seconds.
Instead of mutating your models, any data mutation in your app is described as a plain object describing “what happened” (e.g. { type: LIKED_POST, postId: 42 }) and broadcasted globally. Models (called Stores in Flux) have no setters and change their internal state in response to specific mutation objects (called Actions).
The goal of Flux is to have single source of truth and make it easy to avoid race conditions and cascading updates. If some data is wrong, just repeat the same Actions in the same order, and you'll get the same data in Stores. Very easy to debug.
Now, for Redux.
It keeps the properties of Flux (mutations described as objects), but instead of Stores mutating internal state, it has Reducers—pure functions with (state, action) => state signature. While writing Flux apps, I noticed that the _essence_ of every Store I ever wrote was a reducer function.
It turns out that using pure functions instead of event emitters has many benefits: they are composable (https://gist.github.com/gaearon/d77ca812015c0356654f), it is possible to hot reload their logic (https://camo.githubusercontent.com/5688a6141e6a86baca5d25246...).
I wrote Redux for my React Europe talk about Hot Reloading and Time Travel (https://github.com/react-europe/cfp-2015/blob/master/live-re...). It got popular before I explained _why_ I made it. In my talk I show what kind of powerful devtools it is possible to build on top of Redux. The video of my talk will be up soon, you can check when it appears here: https://www.youtube.com/channel/UCorlLn2oZfgOJ-FUcF2eZ1A?app....
Also check out my article on the subject: https://medium.com/@dan_abramov/the-evolution-of-flux-framew...
EDIT: THE VIDEO IS UP! https://www.youtube.com/watch?v=xsSnOQynTHs
[0] https://hackage.haskell.org/package/foldl-1.1.0/docs/Control...
[1] https://hackage.haskell.org/package/machines-0.5.1/docs/Data...
Great job. Hot reloading is SO HOT .. in your hands!
Would you please share your plans for Redux, Redux DevTools and other tools you are working on?
What's your vision for React based tools in such quick changing environment?
I'm really scared to move all my projects to React base cause constant breaking changes. Coming packages splits in React 0.14, rush into ES6/7 rewrites, etc. is a huge hit for guys like me who can code only in free time outside of standard business hours.
I would rather follow someone with strong vision ;))) ... and it seems you got your own.
Please share what's on your mind.
P.s. And yee ... please do presentation at MoscowJS ;)) http://www.moscowjs.ru/ https://www.facebook.com/groups/moscowjs/ Ilya S
Redux looks awesome. I am using react-dnd and hot reloader on my current project and they are great. Thank you for all the great contributions you are making to the ecosystem.
The idea of modeling the store as a reducer is clever. Complication I see is that my action creators are often not pure functions (i.e. there is generally a side effect to update the database and persist the change). However, given the focus of redux on improving the dev workflow, I suppose database updates/side effects could be mocked out. How would you handle this scenario?
What would actually be awesome to have and go hand-in-hand with redux is an immutable write-only isomorphic database (for application state persistence), where you use the same initial state/reducer for redux and the database. Database stores initial state, logs actions and computes the current state using the reducer (and caches it) - much like redux on the client. Curious to hear what people think about this or if anyone has seen anything like it.
https://github.com/facebook/flux is this the flux it's for?
It seems opaque to me at this stage. It reminds me of when Google released Polymer. There was a lot of generic stuff - but no elevator pitch.
Explain to me in 30 seconds what's flux and where it sits?
Flux is an architecture pattern for applications where a lot of logic can run on the client. Its goal is to disconnect changes to state (the "model" in MVC terms) from the effect that should have on the view. This assumes that the view is a layer that can cheaply update itself without knowing what part of the state changes - a full "re-render" should be cheap and effective. React is a library that allows this.
Once the view can update itself without knowing what state changed, one side of the disconnect between state and UI has been solved. The other side is how to manage state when user actions change it.
When the model is a big blob of mutable data, this is easy: just update whatever you want to update, trigger a full re-render of the view and be done with it. But this has two disadvantages: first, it's often difficult to serialize this model and send it over the wire, which means prerendering on the server for snappy startup times is difficult. Second, people often prefer the model layer to be built of immutable data, because that makes React re-rendering faster.
Flux tries to make working with serializable, immutable data easier by introducting what they call a "unidirectional data flow": user actions go into a "dispatcher", which in term knows which little sub-part of the model, called a Store, wants to turn that action into a data change. The stores, in turn, tell the view to re-render and that's it. The view can query the stores but not change the data in them: that's done only by sending actions through the dispatcher.
The core insight of Flux is that dealing with immutable data is pretty easy if you split the model up into a limited number of simple "Stores", the granularity of which determines much of how well Flux works for you. If you manage to get them not too big and not too small, dealing with immutable data is not difficult anymore and React gets snappy updates. And serializing immutable data to JSON is pretty easy, because it's guaranteed to be a tree, so prerendering both the HTML and the initial dataset on the server is a done deal.
Sorry, not 30 seconds. Does this help at all?
Personal commentary: I'm not convinced that Flux is the final solution. Before Flux was popular, I led a React team with a model layer that was plain old mutable JavaScript objects, and it worked remarkably well. It was a big cyclic graph of objects that all referred to one another. Typical oldschool OO data model design. The big disadvantage was that re-rendering was slower, but IMHO we need to find a better solution around that.
The guys who invented React said "what? all that spaghetti code just to keep model and HTML in sync? i just want to rerender every time just like we used to do with PHP on the server! i'm going to find a workaround" and invented the virtual DOM. In the same spirit, there has to be a way to make mutation of state simpler and still be fast and support universal ("isomorphic") apps. Mutable state is rather unpopular these days, but if there's one place where it shines, it's UI development.
I'm feeling this in a back-end app and I'm wondering whether I can make use of some of these concepts to make things more manageable.