As a software developer, we all must have heard about state machines at some point in time. A finite state machine is pretty famous in designing algorithms like calculating the output on the basis of the series of inputs or calculating the next state based on the output from the current and previous states.
There are many popular examples of state machines which you must have heard.
- Traffic Lights ๐ฆ
- Vending Machine โ๏ธ
- An Elevator ๐ช
Since the state machine is a very compact way to represent a set of complex rules and conditions so let's find out how we can extend its use in our frontend applications.
Why do we need State Machine on Frontend?
State management in the browser has always been a tricky part, especially when working on large applications that have complex state management. The UI framework has a major role to take our application state and turn it down to the DOM node for achieving the desired result.
State Machine is a very useful way of modeling states in an application such that the application can be in only one state at any given point of time. All these benefits will help us to solve issues related to the scaling of our applications which eventually requires new events, new corner cases, etc.
Starting with our Application.
Let's begin by creating a simple Todo Application in Vue.js using Xstate.
The first step is to determine all the possible UI states needed to create a TodoList. I began jotting down the basic states and actions which are required for the application.
There will be some basic states like idle, loading, resolved, rejected
Set of actions required in the application will be update list, create new todo item, update a todo item and delete a todo item
The edit, delete and create will be parallel states as the user can perform all the three actions simultaneously.
Using the above pointers I have created a basic state chart on Xstate Viz covering all the states and actions of my application.
The state machine definition code:
Machine(
{
id: 'Todo',
initial: 'idle',
context: {
user: null,
todoList: [],
delay: 0
},
states: {
idle: {
on: {
fetch: 'list'
}
},
list: {
invoke: {
id: 'fetchList',
src: (context, event) => {
return context.todoList
},
onDone: {
target: 'resolved'
},
onError: 'rejected'
},
on: {
listItems: {
target: 'todoItemActions',
actions: 'addListItem'
// actions: ['fetchListItems']
}
}
},
resolved: {
type: 'final'
},
rejected: {
on: {
fetch: 'list'
}
},
todoItemActions: {
type: 'parallel',
states: {
createTodoItem: {
initial: 'add_details',
states: {
idle: {
on: {
create: 'add_details'
}
},
add_details: {
on: {
fillDetails: {
target: 'createSuccess',
actions: 'createNewTodoItem'
}
}
},
createSuccess: {}
}
},
deleteTodoItem: {
initial: 'idle',
states: {
idle: {
on: {
select_item: 'deleteItem'
}
},
deleteItem: {
on: {
delete: {
target: 'deleteSuccess',
actions: 'deleteTodoItem'
}
}
},
deleteSuccess: {}
}
},
editTodoItem: {
initial: 'idle',
states: {
idle: {
on: {
edit: 'edit_details'
}
},
edit_details: {
on: {
fill_details: {
target: 'editSuccess',
actions: 'editTodoItem'
}
}
},
editSuccess: {}
}
}
}
}
}
},
{
actions: {
createNewTodoItem: (context, event) => {
console.log('create new todo item', context)
},
addListItem: (context, event) => {
console.log('add list item', context, event)
},
deleteTodoItem: (context, event) => {
console.log("delete todo item", context, event)
},
editTodoItem: (context, event) => {
console.log("edit todo item", context, event)
}
}
}
)
You can check the above state machine definition on Visualizer
In the next post, I will be covering the integration and creation of the Todo App using Xstate in Vue js.
There are few awesome articles on the web from where I got the inspiration, do check them out!๐
Top comments (4)
This is awesome, looking forward to the next post!
Thank you so much, I really enjoyed working on Xstate. It is super amazing! ๐
Nicely written!
Thank you!