To keep scope small I will talk about UI race conditions initiated by the same user in the same app sessions. The question is general and not specific to mobile, web or desktop UI.
Modern UI expected to be responsive i.e. commands triggered by user executed asyncronously while UI remains responsive and available. This is perfect breeding ground for all sorts of race conditions because async command can potentially take a lot of time (e.g. if connection is slow/unresponsive) and during that time user can initiate potentially conflicting command in parallel.
There are "bruteforce" workarounds such as make all command synchronous or disable screen / show blocking progress bar or ring for any command / blocking modal dialogs etc. however I don't consider them here.
In my experience it's a serious mental overhead to keep track of all UI elements that can potentially lead to race conditions / conflicting commands and remember to enable/disable them accordingly. The payoff (better UX) is not always worth it. Rx/Reactive programming makes it easier to automatically enable/disable UI elements but it doesn't relieve need to keep many dependencies in one's head. It's especially bad when many people work on a project and write different components/views separately.
For example consider a simple app for editing orders. Order has lines. There are some asynchronous commands (e.g. they all eagerly write to database or other backend).
Order commands (with UI elements)
- Delete (button)
- Change customer (dropdown)
- Change shipping date (calendar)
- Confirm (button)
- Create line (new row in grid)
- Edit line (row in grid)
- Delete line (button)
It's easy to come up with examples of commands which are safe or not safe to run concurrently. E.g. it's OK to edit a line and delete another line at the same time as these commands don't interfere. It's OK to change order shipping date while lines are being saved (shipping date doesn't affect lines), but it's not not OK to change order's customer (e.g. it will refresh pricing for lines i.e. no line command should be in progress). Let's say we add rule that only order without lines can be deleted, now Delete Order button must be disabled if there's any line command (e.g. add line) in progress... And so on and so forth.
In large apps there are more entities and dependencies between them and hence risk of more subtle race conditions.
Example is for illustration only, the question is more general.
Do you know any disciplined approach to maintain good balance between UX/responsiveness and risk of allowing conflicting commands/race conditions? I don't expect a silver bullet and suppose that answer won't be short and will accept relevant links to other resources or books as answers. Any platform or language will do but ideally it has to be in spirit of Rx / (functional) reactive programming.
UPDATE based on discussion, people wonder what kind of application may need to care about it because simple sales order app is not a motivating example. I agree: a better example would be Visual Studio or your favorite IDE: some commands disabled while build is running / while sources being fetched from git etc. We don't want to be locked out of IDE on every background command and those commands can last a while. It's very likely that projects like IDE use very systematic approach to avoid conflicting commands (and if it's simple and elegant enough then why can't a sales orders kind of app benefit from it)