dumb and smart components + redux (1)
TRANSCRIPT
Dumb and smart components & reduxBrecht Billiet
About me
Brecht BillietFrontend Architect - Coach - Trainer
http://brecht.io @brechtbilliet
Who still uses ng-controller and ng-include?
Doesn’t that bother you?
● What HTML belongs to what JS?
● Where do the templates live?
● Absolute template-paths are not maintainable
● What logic belongs in a controller or directive?
● This template should contain... oh wait, there is an ng-include there.
● How do you pass data to your controllers?
Think in components...
● 1 piece HTML + 1 piece LOGIC = COMPONENT
● You know it as: element directives
● Custom DOM tags
● A component has a single responsability
● We could use webcomponents + shadow DOM
● Sandboxed work
● Note: angular 1.5 has new component syntax
What should you refactor to components?
Everything is a component
● Your application is a tree of components
● Your pages are components
● Even your application is a component
applicationHtml + js+ css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
applicationHtml + js+ css
fooPage
html + js + css
html + js + css
barPage
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
html + js + css
Routingconfig:template: ‘<foo-page/>’
Routingconfig:template: ‘<bar-page/>’
Easier to debug
Other advantages
● No scope soup
● Nice hierarchy view
● Single responsability
● No more absolute paths
● Easier to reason about
● Easier to refactor
● Easier to upgrade to ng2
What about attribute-directives?
● Let’s call them behaviors from now
● They add some logic to existing or custom components
● Separate them from your components folder
DEMO
Any rules of thumb?
Keep them small...
Keep them dumb where possible...
Dumb component Smart component (container)
Doesn’t know about the application
Knows about the application
Doesn’t do data fetching Does data fetching
Main purpose is visualization Interacts the application
Reusable Not reusable
Only communicates with its direct parent
Passes state and data to its children
Doesn’t do state management Does state management
http://winecellar.surge.sh: Smart components
http://winecellar.surge.sh: Dumb components
State management
● State is very hard to manage in SPA’s
● State can be
○ data: results from REST calls
○ “sidebar is collapsed” or “spinner is active”
○ Which tab is currently active
State management
● 3 types of state
○ Data state
○ Application state
○ Inner state (e.g value of textbox) We don’t have to persist nor manage that
Why is it so hard to manage?
● 1-way databinding and 2-way databinding
● javascript references that are being broken and sometimes kept
● We can mutate the data in a million different ways
● No structure
● Data flows in different directions
application
state & logic
state & logic
state & logic
state & logic
state & logic
state & logic
state & logic
state & logic
state & logic
state & logic
Without flux
1
2
5 6
3
7 8
4
9
10 11
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
I’m sending an event upwards
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
I’m sending an event upwards
I’m sending events downwards
Without flux
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
I’m sending an event upwards
Without fluxI’m sending events downwards
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
I’m sending an event upwards
I get my data from model x and I can update it here I get my data
from model z
Without fluxI’m sending events downwards
I get my data from model y
1
2
5 6
3
7 8
4
9
10 11
I changed
So did I
My changes should reflect 6 and 4
I have to subscribe before 8 sends a message
I’m sending an event upwards
I get my data from model x and I can update it here I get my data
from model z
Without fluxMy data is passed by twoway binding
I’m sending events downwards
I get my data from model y
My data is passed by oneway binding
My data is passed by twoway binding
Where do those states/events come from?
Who updated my state??
Who updated/notified which component?
Flux helps with that
● Brings structure in data flow
● Not a framework but an architecture by facebook
● Unidirectional dataflow, oneway databinding
● Data flows from the top down
● Easier to reason about state
● Action○ Has an action type and a payload
● Dispatcher○ Dispatches the actions to the store
● Store○ Contains state
● ViewComponents
● The unidirectional dataflow makes it easy to reason about
I use Redux!
Redux is based on flux, but it’s easier
Redux
● Written by Dan Abramov (Facebook)
● Easier to use and less bloat
● Only has one store!!
● Completely Immutable data structure
● Uses reducers (pure functions)
● Flux approves
1
2
5 6
3
7 8
4
9
10 11STORE
1
2
5 6
3
7 8
4
9
10 11
Me too
Me too
Me too
Me too
STORE
I only send actions upwards to the store
I’m the single-source-of-truth in your application!! ;-)
1
2
5 6
3
7 8
4
9
10 11
Me too
Me too
I’m dumb I’m dumb
I’m dumb I’m dumb
I’m dumb
I’m dumb
STORE
Me tooI only send actions upwards to the store Me too
I’m the single-source-of-truth in your application!! ;-)
Dumb components only notify their direct parents!
No state management needed here :-)
What’s different?
● We have one single source of truth: the store
● We don’t update state ourselves anymore, the store handles all the state of our application
● State is immutable
● Actions are always sent upwards
What’s different?
● Dumb components don’t do state management
● State is being updated by pure functions (reducers)
● When the store is updated it notifies all the smart components
Application state
Actions
● Actions have a type and a payload
● Keep the types together, gives clear overview
Actions
Reducers
● Pure functions
● reducer(state: MyState, action: Action): MyState
● they update the state
● Completely immutable
Reducers
Example in container
Middleware
● Easy logging, debugging
● Reproducible action state (pushable to server)
● Timetraveling with redux-devtools (requires react to be bundled in the angular project)
Check it out
● egghead.io course (Free)
○ https://egghead.io/series/getting-started-with-redux
Special thanks to
● Kwinten Pisman (@kwintenp)
● Jurgen Van de Moere (@jvandemo)
Questions?
One more thing
Angular2, rxjs, redux, @ngrx/store, Typescript, webpackhttp://workshop.brecht.io @brechtbilliet
WorkshopJune 2016
Thank you!