State management
This page aims to give an introduction to state management for editor extensions.
This page aims to distill the official CodeMirror 6 documentation for Obsidian plugin developers. For more detailed information on state management, refer to State and Updates.
State changes
In most applications, you would update state by assigning a new value to a property or variable. As a consequence, the old value is lost forever.
let note = "";
note = "Heading"
note = "# Heading"
note = "## Heading" // How to undo this?
To support features like undoing and redoing changes to a user's workspace, applications like Obsidian instead keep a history of all changes that have been made. To undo a change, you can then go back to a point in time before the change was made.
State | |
---|---|
0 | |
1 | Heading |
2 | # Heading |
3 | ## Heading |
In TypeScript, you'd then end up with something like this:
const changes: ChangeSpec[] = [];
changes.push({ from: 0, insert: "Heading" });
changes.push({ from: 0, insert: "# " });
changes.push({ from: 0, insert: "#" });
Transactions
Imagine a feature where you select some text and press the double quote, "
to surround the selection with quotes on both sides. One way to implement the feature would be to:
- Insert
"
at the start of the selection. - Insert
"
at the end of the selection.
Notice that the implementation consists of two state changes. If you added these to the undo history, the user would need to undo twice, once for each double quote. To avoid this, what if you could group these changes so that they appear as one?
For editor extensions, a group of state changes that happen together is called a transaction.
If you combine what you've learned so far—and if you allow transactions that contain only a single state change—then you can consider state as a history of transactions.
Bringing it all together to implement the surround feature from before in an editor extension, here's how you'd add, or dispatch, a transaction to the editor view:
view.dispatch({
changes: [
{ from: selectionStart, insert: `"` },
{ from: selectionEnd, insert: `"` }
]
});
Next steps
On this page, you've learned about modeling state as a series of state changes, and how to group them into transactions.
To learn how to manage custom state in your editor, refer to State fields.