Animating out needs the element mounted a little longer than the state says. Model it as phases: hidden (not in the DOM), entering, shown, leaving. Write presenceReducer(phase, event) for the events open, close, entered and exited (the last two are what transitionend reports). open works from hidden and leaving (interrupting a close). close works from shown and entering. entered only counts while entering, and exited only while leaving: a late event from an interrupted animation must be ignored. Everything else returns the same phase. Also write isMounted(phase).