It is very unintuitive (and genius at the same time) how it works! I was looking at it imperatively, and was not considering that onChange is a ViewModifier and I should think declarative.
So the only reason an API like onChange is working, is because when @State changes, view re-renders, body is called again, hence this onChange method is called with the latest L-Value of View's @State. Which now the ViewModifier can compare it with its local storage.
Im not sure about state, but observable object's @Published properties use a hidden feature of property wrappers, which allows you to access the parent type. I imagine @State might leverage this somehow?