Difference between onEndEditing and onBlur?

React Native has a TextInput component to accept user inputs and I'm interested in the difference between

onEndEditing

Callback that is called when text input ends.

onBlur

Callback that is called when the text input is blurred.

Is there a scenario where it can't be solved just with onBlur, when is onEndEditing useful?


First let me say I was struggling finding the answer to this question!

I believe this is rooted in history since it originates from iOS which has the native event UIControlEventEditingDidEnd. That's probably the naming before blur was introduced as an abstraction.

TL:DR;

onEndEditing should really be deprecated in my opinion, but as of right now you should use it because it is the most platform agnostic version of blur. See below.

Both onBlur and onEndEditing get an event. On iOS both of these seem to do the exact same thing, and the event has the native text. In Android, it is two different events, and only one of them has access to the text. To me this seems like a bug.

Notice the differences between Android onEndEditing and Android onBlur.

// this is undefined on Android
onBlur={(e) => alert(e.nativeEvent.text)}

So if reading the text during a blur, you get cross-platform usability with onEndEditing for now.

See this rnplay to see the differences in OS


Looking at the iOS and Android examples, seems like onEndEditing is meant to pass the contents of the TextInput, while onBlur is not meant to pass any data:

  • iOS example
  • Android example

There is actually a difference between when these events are raised. Here we can see that onEndEditing is raised for native Android onEditorAction, while onBlur is not. The action can be either "Search" (this corresponds to the special "Search" icon on Android keyboards), although I don't know what React Native API lets you display these action icons as part of the keyboard.

In general, looking at examples / implementation is a good way to understand something that's not documented well enough.

If this is unclear in the JS docs, please submit a pull request to clarify it. If the implementation does something that doesn't make sense or is inconsistent between platforms, please submit a pull request to fix the implementation. This should help others.