SlideShare una empresa de Scribd logo
1 de 45
Descargar para leer sin conexión
Are statecharts the next
big UI paradigm?
Luca Matteis
github.com/lmatteis
@lmatteis
Hootsuite office in Rome, Italy
Designers build images of
each possible state of our UI.
When we convert these images
(or states) into code we lose the
high-level understanding of our
app.
var isLoggedIn, isInProgress, isSuccessful;
// display the form
isLoggedIn = false;
isInProgress = false;
isSuccessful = false;
// request in flight
isLoggedIn = false;
isInProgress = true;
isSuccessful = false;
// display a successful message
isLoggedIn = true;
isInProgress = false;
isSuccessful = true;
// display welcome message + links
isLoggedIn = true;
isInProgress = false;
isSuccessful = false;
var isRequestFinished, isInProgress, isSuccessful, isFailed;
if (isInProgress) {
// request in flight, render a spinner
} else if (isRequestFinished) {
if (isSuccessful) {
// request successful, render a message
} else if (isFailed) {
// render error message + try again link
} else {
// render welcome message + links
}
} else {
// waiting for input, render login form
}
As our app grows,
understanding which section is
responsible for each state
becomes increasingly difficult.
Not all questions can be
answered using a set of
images.
• What if the user clicks the submit button repeatedly? 😛
• What if the user wants to cancel the submit while it's in-flight? ✈
• What if the user mischievously enables the disabled button? 😕
• Is there any indication that the request is fetching? 🙄
• What happens if there's an error? Can the user resubmit the form? ❓
• What if the user submits and then clicks a different page? What should
happen? 🤷
It seems we don’t have a
technological problem. We
have a thinking problem.
How do we set ourselves to
answer these questions, and be
able to have both our design
and our code depend on the
answers?
Statecharts
Awake
Day simulator
Dressed
Fed
Ready
Work
Cafe
Home
Asleep
Alarm
Dress
Eat
Eat
Dress
GoToWork
Think
Yawn
Coffee
GoHome
Read WatchTv
Empty form
Submitting
SUBMIT
RESOLVE
REJECT
Welcome
page
Error page
REGISTER
REGISTER
LOGOUT
Login page
REGISTER
Statecharts have 3
important concepts:
1) Hierarchical (nested) states 🌳
2) History states (
3) Parallel states ⏰
Empty form
Submitting
SUBMIT
RESOLVE
REJECT
Welcome
page
Error page
REGISTER
REGISTER
LOGOUT
Login page
REGISTER
Empty form
Submitting
SUBMIT
RESOLVEREJECT
Welcome
page
Error page
REGISTER
LOGOUT
Login page
Hierarchical (nested) states 🌳
Unclustering Welcome page
Login page
GetTickets
TicketsRESOLVE
REFRESH
Empty form
Submitting
SUBMIT
History states
Welcome page
GetTickets
TicketsRESOLVE
REFRESH
H
Parallel states
Welcome page
GetTickets
TicketsRESOLVE
REFRESH
Sidebar
Init
Loading
SEARCH
RESOLVE
Items
These representations can
drive both our design and
our code.
• What if the user clicks the submit button repeatedly? 😛
• What if the user wants to cancel the submit while it's in-flight? ✈
• What if the user mischievously enables the disabled button? 😕
• Is there any indication that the request is fetching? 🙄
• What happens if there's an error? Can the user resubmit the form? ❓
• What if the user submits and then clicks a different page? What should happen? 🤷
Empty form
Submitting
SUBMIT
• What if the user clicks the submit button repeatedly? 😛
• What if the user wants to cancel the submit while it's in-flight? ✈
• What if the user mischievously enables the disabled button? 😕
• Is there any indication that the request is fetching? 🙄
• What happens if there's an error? Can the user resubmit the form? ❓
• What if the user submits and then clicks a different page? What should happen? 🤷
Empty form
Submitting
SUBMIT
SUBMIT
• What if the user clicks the submit button repeatedly? 😛
• What if the user wants to cancel the submit while it's in-flight? ✈
• What if the user mischievously enables the disabled button? 😕
• Is there any indication that the request is fetching? 🙄
• What happens if there's an error? Can the user resubmit the form? ❓
• What if the user submits and then clicks a different page? What should happen? 🤷
Empty form
Submitting
SUBMIT
SUBMIT
CANCEL
• What if the user clicks the submit button repeatedly? 😛
• What if the user wants to cancel the submit while it's in-flight? ✈
• What if the user mischievously enables the disabled button? 😕
• Is there any indication that the request is fetching? 🙄
• What happens if there's an error? Can the user resubmit the form? ❓
• What if the user submits and then clicks a different page? What should happen? 🤷
Empty form
Submitting
SUBMIT
SUBMIT
CANCEL
Error
REJECT
Such diagram can be
described using JSON and
our UI code can directly be
driven by its description.
https://github.com/davidkpiano/xstate
What about setState() and
Redux?
The term state used within
the statechart formalism
simply describes a textual
label which drives our
program in understanding
what needs to happen.
To the contrary, in the
React world the term state
usually describes some
data that we use to render
our components.
Statecharts actually merry
quite well with a system
like Redux.
Redux and Statecharts
const initialState = {
isRequestFinished: false,
isInProgress: false,
isSuccessful: false,
isFailed: false
};
function reducer(state = initialState, action) {
…
}
render() {
if (isInProgress) {
// request in flight, render a spinner
} else if (isRequestFinished) {
if (isSuccessful) {
// request successful, render a message
} else if (isFailed) {
// render error message + try again link
} else {
// render welcome message + links
}
} else {
// waiting for input, render login form
}
}
Redux and Statecharts
const initialState = null;	
function reducer(state = initialState, action) {	
return machine	
.transition(state, action.type)	
.value;	
}
machine = Machine({
initial: 'init',
states: {
init: {
on: {
SUBMIT: ‘submitting’,
},
},
submitting: {
on: {
RESOLVE: ‘success’,
REJECT: ‘error’
}
},
error: {
on: {
TRY_AGAIN: ‘init’,
}
}
}
});
render() {
if (isInProgress) {
// request in flight, render a spinner
} else if (isRequestFinished) {
if (isSuccessful) {
// request successful, render a message
} else if (isFailed) {
// render error message + try again link
} else {
// render welcome message + links
}
} else {
// waiting for input, render login form
}
}
Redux and Statecharts
const initialState = null;	
function reducer(state = initialState, action) {	
return machine	
.transition(state, action.type)	
.value;	
}
machine = Machine({
initial: 'init',
states: {
init: {
on: {
SUBMIT: ‘submitting’,
},
},
submitting: {
on: {
RESOLVE: ‘success’,
REJECT: ‘error’
}
},
error: {
on: {
TRY_AGAIN: ‘init’,
}
}
}
});
render() {
const renderMap = {
[submitting]: // request in flight, render a spinner
[success]: // request successful, render a message
[error]: // render error message + try again link
[init]: // waiting for input, render login form
}
return renderMap[this.props.state];
}
Redux and Statecharts
const initialState = null;	
function reducer(state = initialState, action) {	
return machine	
.transition(state, action.type)	
.value;	
}
machine = Machine({
initial: 'init',
states: {
init: {
on: {
SUBMIT: ‘submitting’,
},
},
submitting: {
on: {
RESOLVE: ‘success’,
REJECT: ‘error’
}
},
error: {
on: {
TRY_AGAIN: ‘init’,
}
}
}
});
store.dispatch({ type: SUBMIT });
store.dispatch({ type: RESOLVE });
store.dispatch({ type: REJECT });
store.dispatch({ type: TRY_AGAIN });
You can continue using
other reducers for other
non-statechart data.
Redux and Statecharts
const initialState = null;	
function reducer(state = initialState, action) {	
return machine	
.transition(state, action.type)	
.value;	
}
store.dispatch({ type: SUBMIT });
store.dispatch({ type: RESOLVE, payload });
store.dispatch({ type: REJECT });
store.dispatch({ type: TRY_AGAIN });
function resolveReducer(state = null, action) {	
switch (action.type) {	
case RESOLVE:	
return action.payload;	
default:	
return state;	
}	
}
Redux and Statecharts
const initialState = null;	
function reducer(state = initialState, action) {	
return machine	
.transition(state, action.type)	
.value;	
}
store.dispatch({ type: SUBMIT });
store.dispatch({ type: RESOLVE, payload });
store.dispatch({ type: REJECT });
store.dispatch({ type: TRY_AGAIN });
function resolveReducer(state = null, action) {	
switch (action.type) {	
case RESOLVE:	
return action.payload;	
default:	
return state;	
}	
}
render() {
const renderMap = {
[submitting]: // request in flight, render a spinner
[success]: renderMessage(this.props.resolveData)
[error]: // render error message + try again link
[init]: // waiting for input, render login form
}
return renderMap[this.props.state];
}
Statecharts provide us with
a visual formalism that can
tie the functioning of our
code and our designs
together.
Whenever you find yourself
writing lots of isSomething
variables in your state,
maybe it’s time to give
statecharts a try!
Further reading:
Pure UI Control by Adam Solove https://medium.com/@asolove/
pure-ui-control-ac8d1be97a8d
STATECHARTS: A VISUAL FORMALISM FOR COMPLEX SYSTEMS
http://www.inf.ed.ac.uk/teaching/courses/seoc/2005_2006/
resources/statecharts.pdf
You are managing state? Think twice. by Krasimir Tsonev
http://krasimirtsonev.com/blog/article/managing-state-in-
javascript-with-state-machines-stent
Infinitely Better UIs with Finite Automata by David Khourshid
https://www.youtube.com/watch?v=VU1NKX6Qkxc
Rambling thoughts on React and Finite State Machines by
Ryan Florence https://www.youtube.com/watch?v=MkdV2-U16tc
Thanks!

Más contenido relacionado

La actualidad más candente

Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
Ivan Chepurnyi
 
Alfresco Share - Recycle Bin Ideas
Alfresco Share - Recycle Bin IdeasAlfresco Share - Recycle Bin Ideas
Alfresco Share - Recycle Bin Ideas
AlfrescoUE
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
moniguna
 

La actualidad más candente (20)

Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)Making Magento flying like a rocket! (A set of valuable tips for developers)
Making Magento flying like a rocket! (A set of valuable tips for developers)
 
Driving containerd operations with gRPC
Driving containerd operations with gRPCDriving containerd operations with gRPC
Driving containerd operations with gRPC
 
LINQ
LINQLINQ
LINQ
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)
 
Redux workshop
Redux workshopRedux workshop
Redux workshop
 
Oracle Forms : Validation Triggers
Oracle Forms : Validation TriggersOracle Forms : Validation Triggers
Oracle Forms : Validation Triggers
 
Alfresco Share - Recycle Bin Ideas
Alfresco Share - Recycle Bin IdeasAlfresco Share - Recycle Bin Ideas
Alfresco Share - Recycle Bin Ideas
 
Oracle Forms : Multiple Forms
Oracle Forms : Multiple FormsOracle Forms : Multiple Forms
Oracle Forms : Multiple Forms
 
Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)Functional Programming Patterns (BuildStuff '14)
Functional Programming Patterns (BuildStuff '14)
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
 
점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정점진적인 레거시 웹 애플리케이션 개선 과정
점진적인 레거시 웹 애플리케이션 개선 과정
 
Lightweight Xtext Editors as SWT Widgets
Lightweight Xtext Editors as SWT WidgetsLightweight Xtext Editors as SWT Widgets
Lightweight Xtext Editors as SWT Widgets
 
Lucene and MySQL
Lucene and MySQLLucene and MySQL
Lucene and MySQL
 
Important React Hooks
Important React HooksImportant React Hooks
Important React Hooks
 
Understanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree TechnologiesUnderstanding React hooks | Walkingtree Technologies
Understanding React hooks | Walkingtree Technologies
 
Type script - advanced usage and practices
Type script  - advanced usage and practicesType script  - advanced usage and practices
Type script - advanced usage and practices
 
The tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptxThe tests are trying to tell you something@VoxxedBucharest.pptx
The tests are trying to tell you something@VoxxedBucharest.pptx
 
Redux Toolkit & RTK Query in TypeScript: tips&tricks
Redux Toolkit & RTK Query in TypeScript: tips&tricksRedux Toolkit & RTK Query in TypeScript: tips&tricks
Redux Toolkit & RTK Query in TypeScript: tips&tricks
 
Railway Oriented Programming
Railway Oriented ProgrammingRailway Oriented Programming
Railway Oriented Programming
 
Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8Clean Lambdas & Streams in Java8
Clean Lambdas & Streams in Java8
 

Similar a Are statecharts the next big UI paradigm?

You should be able to use the same function to check a narrowing fun.pdf
You should be able to use the same function to check a narrowing fun.pdfYou should be able to use the same function to check a narrowing fun.pdf
You should be able to use the same function to check a narrowing fun.pdf
sayandas941
 
Write a C++ program which generates and displays a random walk acros.pdf
Write a C++ program which generates and displays a random walk acros.pdfWrite a C++ program which generates and displays a random walk acros.pdf
Write a C++ program which generates and displays a random walk acros.pdf
mckenziecast21211
 

Similar a Are statecharts the next big UI paradigm? (20)

A Journey with React
A Journey with ReactA Journey with React
A Journey with React
 
iOS 개발자의 Flutter 체험기
iOS 개발자의 Flutter 체험기iOS 개발자의 Flutter 체험기
iOS 개발자의 Flutter 체험기
 
N Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React NativeN Things You Don't Want to Repeat in React Native
N Things You Don't Want to Repeat in React Native
 
Extending Redux in the Server Side
Extending Redux in the Server SideExtending Redux in the Server Side
Extending Redux in the Server Side
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
How Reactive do we need to be
How Reactive do we need to beHow Reactive do we need to be
How Reactive do we need to be
 
The accidental web designer - No Code Conf 2019 Workshop
The accidental web designer - No Code Conf 2019 WorkshopThe accidental web designer - No Code Conf 2019 Workshop
The accidental web designer - No Code Conf 2019 Workshop
 
A short tale about state machine
A short tale about state machineA short tale about state machine
A short tale about state machine
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
Introduction to Redux
Introduction to ReduxIntroduction to Redux
Introduction to Redux
 
The biggest lies about react hooks
The biggest lies about react hooksThe biggest lies about react hooks
The biggest lies about react hooks
 
Roman Schejbal: From Madness To Reason
Roman Schejbal: From Madness To ReasonRoman Schejbal: From Madness To Reason
Roman Schejbal: From Madness To Reason
 
You should be able to use the same function to check a narrowing fun.pdf
You should be able to use the same function to check a narrowing fun.pdfYou should be able to use the same function to check a narrowing fun.pdf
You should be able to use the same function to check a narrowing fun.pdf
 
Imagine a world without mocks
Imagine a world without mocksImagine a world without mocks
Imagine a world without mocks
 
Serverless Functions and Vue.js
Serverless Functions and Vue.jsServerless Functions and Vue.js
Serverless Functions and Vue.js
 
The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)The Functional Programming Toolkit (NDC Oslo 2019)
The Functional Programming Toolkit (NDC Oslo 2019)
 
Let it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTPLet it crash - fault tolerance in Elixir/OTP
Let it crash - fault tolerance in Elixir/OTP
 
The evolution of asynchronous JavaScript
The evolution of asynchronous JavaScriptThe evolution of asynchronous JavaScript
The evolution of asynchronous JavaScript
 
Write a C++ program which generates and displays a random walk acros.pdf
Write a C++ program which generates and displays a random walk acros.pdfWrite a C++ program which generates and displays a random walk acros.pdf
Write a C++ program which generates and displays a random walk acros.pdf
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
 

Último

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Último (20)

MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 

Are statecharts the next big UI paradigm?

  • 1. Are statecharts the next big UI paradigm?
  • 3. Designers build images of each possible state of our UI.
  • 4.
  • 5. When we convert these images (or states) into code we lose the high-level understanding of our app.
  • 6. var isLoggedIn, isInProgress, isSuccessful; // display the form isLoggedIn = false; isInProgress = false; isSuccessful = false; // request in flight isLoggedIn = false; isInProgress = true; isSuccessful = false; // display a successful message isLoggedIn = true; isInProgress = false; isSuccessful = true; // display welcome message + links isLoggedIn = true; isInProgress = false; isSuccessful = false; var isRequestFinished, isInProgress, isSuccessful, isFailed; if (isInProgress) { // request in flight, render a spinner } else if (isRequestFinished) { if (isSuccessful) { // request successful, render a message } else if (isFailed) { // render error message + try again link } else { // render welcome message + links } } else { // waiting for input, render login form }
  • 7. As our app grows, understanding which section is responsible for each state becomes increasingly difficult.
  • 8. Not all questions can be answered using a set of images.
  • 9. • What if the user clicks the submit button repeatedly? 😛 • What if the user wants to cancel the submit while it's in-flight? ✈ • What if the user mischievously enables the disabled button? 😕 • Is there any indication that the request is fetching? 🙄 • What happens if there's an error? Can the user resubmit the form? ❓ • What if the user submits and then clicks a different page? What should happen? 🤷
  • 10. It seems we don’t have a technological problem. We have a thinking problem.
  • 11. How do we set ourselves to answer these questions, and be able to have both our design and our code depend on the answers?
  • 15. Statecharts have 3 important concepts: 1) Hierarchical (nested) states 🌳 2) History states ( 3) Parallel states ⏰
  • 18. Unclustering Welcome page Login page GetTickets TicketsRESOLVE REFRESH Empty form Submitting SUBMIT
  • 21.
  • 22. These representations can drive both our design and our code.
  • 23. • What if the user clicks the submit button repeatedly? 😛 • What if the user wants to cancel the submit while it's in-flight? ✈ • What if the user mischievously enables the disabled button? 😕 • Is there any indication that the request is fetching? 🙄 • What happens if there's an error? Can the user resubmit the form? ❓ • What if the user submits and then clicks a different page? What should happen? 🤷 Empty form Submitting SUBMIT
  • 24. • What if the user clicks the submit button repeatedly? 😛 • What if the user wants to cancel the submit while it's in-flight? ✈ • What if the user mischievously enables the disabled button? 😕 • Is there any indication that the request is fetching? 🙄 • What happens if there's an error? Can the user resubmit the form? ❓ • What if the user submits and then clicks a different page? What should happen? 🤷 Empty form Submitting SUBMIT SUBMIT
  • 25. • What if the user clicks the submit button repeatedly? 😛 • What if the user wants to cancel the submit while it's in-flight? ✈ • What if the user mischievously enables the disabled button? 😕 • Is there any indication that the request is fetching? 🙄 • What happens if there's an error? Can the user resubmit the form? ❓ • What if the user submits and then clicks a different page? What should happen? 🤷 Empty form Submitting SUBMIT SUBMIT CANCEL
  • 26. • What if the user clicks the submit button repeatedly? 😛 • What if the user wants to cancel the submit while it's in-flight? ✈ • What if the user mischievously enables the disabled button? 😕 • Is there any indication that the request is fetching? 🙄 • What happens if there's an error? Can the user resubmit the form? ❓ • What if the user submits and then clicks a different page? What should happen? 🤷 Empty form Submitting SUBMIT SUBMIT CANCEL Error REJECT
  • 27. Such diagram can be described using JSON and our UI code can directly be driven by its description.
  • 29. What about setState() and Redux?
  • 30. The term state used within the statechart formalism simply describes a textual label which drives our program in understanding what needs to happen.
  • 31. To the contrary, in the React world the term state usually describes some data that we use to render our components.
  • 32. Statecharts actually merry quite well with a system like Redux.
  • 33.
  • 34. Redux and Statecharts const initialState = { isRequestFinished: false, isInProgress: false, isSuccessful: false, isFailed: false }; function reducer(state = initialState, action) { … } render() { if (isInProgress) { // request in flight, render a spinner } else if (isRequestFinished) { if (isSuccessful) { // request successful, render a message } else if (isFailed) { // render error message + try again link } else { // render welcome message + links } } else { // waiting for input, render login form } }
  • 35. Redux and Statecharts const initialState = null; function reducer(state = initialState, action) { return machine .transition(state, action.type) .value; } machine = Machine({ initial: 'init', states: { init: { on: { SUBMIT: ‘submitting’, }, }, submitting: { on: { RESOLVE: ‘success’, REJECT: ‘error’ } }, error: { on: { TRY_AGAIN: ‘init’, } } } }); render() { if (isInProgress) { // request in flight, render a spinner } else if (isRequestFinished) { if (isSuccessful) { // request successful, render a message } else if (isFailed) { // render error message + try again link } else { // render welcome message + links } } else { // waiting for input, render login form } }
  • 36. Redux and Statecharts const initialState = null; function reducer(state = initialState, action) { return machine .transition(state, action.type) .value; } machine = Machine({ initial: 'init', states: { init: { on: { SUBMIT: ‘submitting’, }, }, submitting: { on: { RESOLVE: ‘success’, REJECT: ‘error’ } }, error: { on: { TRY_AGAIN: ‘init’, } } } }); render() { const renderMap = { [submitting]: // request in flight, render a spinner [success]: // request successful, render a message [error]: // render error message + try again link [init]: // waiting for input, render login form } return renderMap[this.props.state]; }
  • 37. Redux and Statecharts const initialState = null; function reducer(state = initialState, action) { return machine .transition(state, action.type) .value; } machine = Machine({ initial: 'init', states: { init: { on: { SUBMIT: ‘submitting’, }, }, submitting: { on: { RESOLVE: ‘success’, REJECT: ‘error’ } }, error: { on: { TRY_AGAIN: ‘init’, } } } }); store.dispatch({ type: SUBMIT }); store.dispatch({ type: RESOLVE }); store.dispatch({ type: REJECT }); store.dispatch({ type: TRY_AGAIN });
  • 38. You can continue using other reducers for other non-statechart data.
  • 39. Redux and Statecharts const initialState = null; function reducer(state = initialState, action) { return machine .transition(state, action.type) .value; } store.dispatch({ type: SUBMIT }); store.dispatch({ type: RESOLVE, payload }); store.dispatch({ type: REJECT }); store.dispatch({ type: TRY_AGAIN }); function resolveReducer(state = null, action) { switch (action.type) { case RESOLVE: return action.payload; default: return state; } }
  • 40. Redux and Statecharts const initialState = null; function reducer(state = initialState, action) { return machine .transition(state, action.type) .value; } store.dispatch({ type: SUBMIT }); store.dispatch({ type: RESOLVE, payload }); store.dispatch({ type: REJECT }); store.dispatch({ type: TRY_AGAIN }); function resolveReducer(state = null, action) { switch (action.type) { case RESOLVE: return action.payload; default: return state; } } render() { const renderMap = { [submitting]: // request in flight, render a spinner [success]: renderMessage(this.props.resolveData) [error]: // render error message + try again link [init]: // waiting for input, render login form } return renderMap[this.props.state]; }
  • 41. Statecharts provide us with a visual formalism that can tie the functioning of our code and our designs together.
  • 42.
  • 43. Whenever you find yourself writing lots of isSomething variables in your state, maybe it’s time to give statecharts a try!
  • 44. Further reading: Pure UI Control by Adam Solove https://medium.com/@asolove/ pure-ui-control-ac8d1be97a8d STATECHARTS: A VISUAL FORMALISM FOR COMPLEX SYSTEMS http://www.inf.ed.ac.uk/teaching/courses/seoc/2005_2006/ resources/statecharts.pdf You are managing state? Think twice. by Krasimir Tsonev http://krasimirtsonev.com/blog/article/managing-state-in- javascript-with-state-machines-stent Infinitely Better UIs with Finite Automata by David Khourshid https://www.youtube.com/watch?v=VU1NKX6Qkxc Rambling thoughts on React and Finite State Machines by Ryan Florence https://www.youtube.com/watch?v=MkdV2-U16tc