🇫🇮
Renderer = View
(State)
Renderer = View
(State)
Behavior
Renderer = View
(State)
before fetching
after fetching
isFetching: true
type FetchingState =
| BeforeFetching
| Fetching
| FetchedValidData
| FetchedCorruptedData
| FetchedError
type LayoutProps = {
main?: boolean;
header?: boolean;
right?: boolean;
}
type LayoutProps = {
main?: boolean;
header?: boolean;
right?: boolean;
}
<Layout main />
<Layout header />
<Layout right />
8
3
type LayoutType =
| Main
| Header
| Right
<MainLayout />
<HeaderLayout />
<RightLayout />
type LayoutProps = {
main?: boolean;
header?: boolean;
right?: boolean;
}
const layoutProps = {
isMain: false,
isHeader: false,
isRight: false
}
Uncertainty
Limited values
Complexity growth
Priority will matter
isLoading: boolean
isMain: true;
isHeader: true;
const ArticleList = ({list}) => {
return (
{list.length === 0 ? <p>Empty list</p> : null}
)
}
const Article = ({ article }) => (
<div>
{article.pictures.length ? (
<>
<Picture src={article.pictures[0].url} />
<PictureCaption>{article.pictures[0].caption}</PictureCaption>
</>
) : null}
</div>
);
switch(event.type) {
case "SET_CHECKING":
return {
...state,
checking: true,
error: undefined
}
case "CHECK_SUCCESS":
return {
...state,
checking: false,
status: event.payload
}
case "CHECK_FAILURE":
return {
...state,
checking: false,
error: event.payload
}
default:
return state;
}
{
status: undefined,
checking: false,
error: undefined
}
type HealthCheckState
=
| Idle
| Checking
| Success status
| Failure error
{
status: undefined,
checking: false,
error: undefined
}
document.getElementById("button")
.addEventListener("click", e => {
// Run side effects
})
dispatch({ type: "authorize_session" });
function authorizeHandler(state) {
if (state.session.isLoggedIn) {
dispatch({ type: "session_authorized" });
} else {
if (isSessionValidForRefreshing(state.session.lastLoggedIn))
{
dispatch({ type: "retry_session" });
} else {
if (state.session !== undefined) {
dispatch({ type: "session_logout" });
}
}
}
}
login()
logout()
checkout()
addToCart()
LoginView
LogoutView
CheckoutView
CartView
FSM(State + Event) => NextState + SideEffects
Purity vs Idempotence
Reducing logic
Finite state machines
Machine({
id: "session",
initial: "logged_out",
states: {
logged_out: {
on: {
LOGIN: "authorizing"
},
id: "session_error",
initial: "empty",
states: {
empty: {},
present: {
onEntry: "showError",
on: {
RETRY: "authorizing"
}
}
}
},
logged_in: {
on: {
LOGOUT: "authorizing"
}
},
authorizing: {
on: {
SUCCESS: "logged_in",
ERROR: "logged_out"
}
}
}
})
type State =
| { type: "location_pending" }
| { type: "location_supported.zone_idle" }
| { type: "location_supported.zone_pending" }
| { type: "location_supported.zone_error"; error: string }
| { type: "location_supported.zone_available.not_watching"; zone: Zone }
| {
type: "location_supported.zone_available.watching.listening";
zone: Zone;
watchId: number;
}
| {
type: "location_supported.zone_available.watching.updating";
zone: Zone;
watchId: number;
};
MAKE IMPOSSIBLE STATES IMPOSSIBLE
Making Impossible States Impossible by Richard Feldman
MAKE IRRELEVANT DATA UNAVAILABLE
DO NOT TEST SOMETHING THAT IS NOT SUPPOSED TO HAPPEN
TESTING IS GOOD.
IMPOSSIBLE IS JUST BETTER.
Making Impossible States Impossible by Richard Feldman