Member-only story
TextFieldState is a document, and edits are transactions on it
Undo, selection, IME composition — the machinery Day 38 skipped, and why editing through state.edit is different from replacing a String.
Day 52 of 100. Day 38 introduced TextFieldState and the cursor problem. Today: what else it holds, and why editing it looks the way it does.
The case this post is about
One clear button that breaks undo:
IconButton(onClick = { state.setTextAndPlaceCursorAtEnd("") }) {
Icon(Icons.Default.Close, contentDescription = "Clear")
}
It clears the field correctly. Press undo afterwards and you do not get the text back — you get something from several keystrokes earlier, or nothing at all, depending on how the field had been edited before.
The field holds three things that move together: the text, the selection, and the IME composing region. Replacing the text wholesale tells the buffer that everything changed and has no relationship to what came before, so the undo history has nothing coherent to step back into.
This post follows that one button, because the fix is the same operation expressed as a transaction, and the difference is invisible at the call site.
The symptom
A “clear” button that breaks undo:
IconButton(onClick = {…









