Fluxy
Fluxy (adj): characteristics inherited / inspired by Facebook's Flux Architecture
Fluxy and Flux refer to the pattern
not specifically Facebook's Flux implementation
throughout this presentation...
What is the Flux Pattern?
What is Flux?
- more of a pattern or architecture rather than a formal framework
- vs. a MV* pattern
- creating a shift in the front-end landscape (and beyond)
- popularized by Facebook's Flux & React
- not Facebook Flux & React specific; many possible implementations
- Flux, Reflux, Redux, Fluxxor, etc
- React, Riot, etc
- with superhuman discipline, you could implement it in about anything (even NG) ;-)
Why a New Pattern?
Why not traditional MV*?
https://facebook.github.io/flux/docs/overview.html
http://fluxxor.com/what-is-flux.html
abnormally simple MVC
model
view
controller
action
- arrows represent an interaction between the different parts of the system
- an action invokes some functionality in the controller
- the controller potentially updates the model
- the model changes are reflected in the view
- user interaction in the view can change the model directly (2-way binding) or kickoff an action.
Adding a Couple of Views
https://facebook.github.io/flux/docs/overview.html
http://fluxxor.com/what-is-flux.html
abnormally simple MVC
model
view
controller
action
view
view
Adding Another Model
https://facebook.github.io/flux/docs/overview.html
http://fluxxor.com/what-is-flux.html
abnormally simple MVC
model
view
controller
action
view
view
model
Approaching Real World Conditions
https://facebook.github.io/flux/docs/overview.html
http://fluxxor.com/what-is-flux.html
still a pretty simple MV*
model
view
model
view
model
view
model
view
model
view
model
view
model
view
controller
controller
No 2-Way Binding?
https://facebook.github.io/flux/docs/overview.html
http://fluxxor.com/what-is-flux.html
still a pretty simple MV*
model
view
model
view
model
view
model
view
model
view
model
view
model
view
controller
controller
still problematic at scale
prone to bugs
that are hard to debug
hard for humans to reason with
Scope Creep
model
view
model
view
model
view
model
view
model
view
model
view
model
view
to fully understand this
<---------
{
you must understand all this
and know all the places where state can be mutated
}
and maybe this
and potentially how
controller
and maybe this
Banana vs Jungle
maybe these
difficult
- to undertand
- when inheriting such a project
- to onboard new devs
- to maintain
- to add new features
- to test
- etc
How is Flux Different?
How is Flux Different?
1. Unidirectional Data Flow
"Data Flows Down"
view
model
{}
</>
- subscribes to store
- reacts to store's state
- stateless*
- can't change itself directly*
- no imperative manipulations
- a pure function of state
- no scope creep
- contains the model
- the model can't be changed directly
- allows subscribers
- notifies listeners when changes to state occur
store
view
store
{}
</>
smart component
</>
</>
</>
dumb components
- subscribes to store
- reacts to store's state
- stateless*
- can't change itself directly*
- a pure function of state
- composes dumb components
- aka: Controller-Views
- contains the entire apps' state / view-model
- immutable or not directly mutable
- notifies listeners when changes to state occur
- 100% decoupled*
- from store, smart component, each other
- pure / reactive
- reusable
- composable
- all dependencies injected via props*
view
all completely reactive to store
export default ({ people }) => {
let list = people.map( person => (
<li>
<strong>{ person.name }</strong>
: <small>{ person.about }</small>
</li>
));
return people.length
? <ul>{ list }</ul>
: <strong>No Peeps</strong>;
};
Dumb Component (JSX)
- No Dependencies
https://jsbin.com/qeguge/edit?js,output
{}
</>
</>
</>
</>
Pop Quiz
How do I change the rendered UI of this component?
Change the state in the store.
Okay, so how do you change the state in the store?
How is Flux Different?
2. Store vs Model
Store
-
contains the model / state
- is a plain old JS object (POJO)
- single source of truth
- only place in app where state is kept
- contains the logic to change its state
- predefined list of all mutations called Action Handlers (or reducers)
- mutations are always synchronous
-
listens for and reacts to dispatched Actions
- no traditional getters / setters
- change requests are broadcasted in
- can't mutate state in any other way
- emits notifications to subscribers when changes occur
- -------
- -------
- -------
{}
Store
model / state
notifier
action handler(s)
listener
regarding the store: as an app dev, you only write action handlers
- -------
- -------
- -------
{}
Actions
- plain old JavaScript object (POJO)
-
type key names the mutation
- only required key
- unique across app (or collisions)
- the rest of the structure is up to you
- minimalism recommended
{
"type": "ADD_PERSON",
"name": "Jared",
"location": "South Jordan, UT",
"food": ["pizza", "bacon"]
}
example action
action handler
to understand action handlers, let's talk...
Actions & Handlers
{
"type": "INCREMENT_COUNTER"
}
function myCounter(state=0, action) {
switch(action.type) {
case "INCREMENT_COUNTER":
return state+1;
case "DECREMENT_COUNTER":
return state-1;
default:
return state;
}
}
- usually a switch statement
- checks for a matching`action.type`
- optionally performs the mutation
action handler
action
- asks store to make a mutation, hangs up
- blissfully ignorant
- current state
- how mutations occurs
- if mutation occurs
Example Store (Redux)
import { createStore } from 'redux'
function todos(state = [], action) {
switch (action.type) {
case 'ADD_TODO':
return state.concat({
task: action.item,
id: state.length+1
});
case 'REMOVE_TODO':
return state.filter(item=>item.id!==action.id);
default:
return state
}
}
let store = createStore(todos);
store.subscribe( () => console.log(
store.getState()
));
https://jsbin.com/quyotan/edit?js,console
How is Flux Different?
3. Actions Float Up
- -------
- -------
- -------
{}
store
action creators
</>
</>
</>
</>
view
action
handlers
state
notify
smart component
dumb components
What's Missing?
dispatched action
listener
action creator
Action Creators
- a function which returns an action object
- abstracts away the details of the action object structure
- where you'd find async code that talks to servers
- it's the upstream glue between the store and smart-components
dispatched action
Action Creators
export function addTodo(text) {
return {
type: ADD_TODO,
text
};
}
http://rackt.org/redux/docs/basics/Actions.html
import { dispatch } from './store.js';
import { addTodo } from './actions/add-todo.js';
import { Dumb } from './components/dumb.js';
// to be passed into dumb component(s)
let add = text => (
dispatch( addTodo(text) )
);
// later usage:
<Dumb addAction={add} />
../actions/add-todo.js
./some/smart-component.js
How is Flux Different?
4. Distinct, Composable Parts
Quick Poll
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
who believes they:
- decently understand this whole system?
- are ready to write a fluxy app now (if provided a project-starter)?
- understand parts, but are still making the connections?
- are completely lost?
you know what's awesome?
you don't need to understand the whole jungle to start writing bananas!
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
Of this system, these are the things you write
- action creator(s)
- action handler(s)
- smart components
- dumb components
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
Action Handlers & Dumb Components
- are blissfully ignorant of any other part of the jungle
- provided a few rules, any developer* could start writing these today
- are pure functions & have no library dependencies
- it may be preferable to write these without knowledge of any other part of the app
- are application agnostic / extremely reusable
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
Action Creator
- no coupling, high cohesion
- only need to know emitted action's structure
- more app specific, but decoupled enough for potential reusability
- also export their functionality
thus, requires some awareness of the system
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
Smart Component / Controller-View
- it imports the store to which it subscribes
- it imports and composes dumb components
- it imports and composes actions
- subscribes to the store
- disperses data and actions to dumb components
- is app specific
- essentially is just a smart composition
Distinct Units
- reusable
- repeatable
- extensible
- composable
- SRP
- pure function
- encapsulated
- swappable
each unit is:
- TESTABLE!
How is Flux Different?
5. Scales Gracefully
FTW
Fluxy Scalability
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
dumb components
action
listener
action creator
state
notifier
start with
- 2 action creators
- 1 action handler / reducer
- 1 smart component
- 3 dumb components
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
action
listener
action creator
state
notifier
</>
</>
</>
</>
</>
</>
Add Dumb Components
no effect on system complexity
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
action
listener
action creator
state
notifier
</>
</>
</>
</>
</>
</>
Add Smart Components
</>
</>
no effect on system complexity
- -------
- -------
- -------
{}
</>
</>
</>
</>
action
handlers
smart component
action
listener
action creator
state
notifier
</>
</>
</>
</>
</>
</>
Add Action Handlers
may result in more action creators
- -------
- -------
- -------
- -------
- -------
- -------
- -------
- -------
- -------
but no increase in system complexity
</>
</>
so, as your app grows bigger...
complexity
does not!!
Other Visual Representations
per Google Image search ;)
action
view
store
dispatch
action creator
smart component
store
dispatch
dumb component
api
user
interaction
a playground
https://jsbin.com/sagafug/edit?js,output
What Does the Flux Say?
By Jared Anderson
What Does the Flux Say?
- 1,562