IonInput doesn't update state after upgrading to v7

Using this Ionic code, typing in the input field doesn’t update the state. I can see in the console logs that “CHANGE TRIGGERED” never shows and when I click “Enter” to login it displays the PW as “”.

                    <IonInput
                        label={"Password"}
                        labelPlacement={"floating"}
                        ref={passwordFieldRef}
                        type="password"
                        value={password}
                        onIonChange={(e) => {
                            console.log("CHANGE TRIGGERED")
                            setPassword(e.detail.value!)
                            console.log("PW:", password)
                        }}
                        onKeyDown={(e) => {
                            if (e.key === "Enter") {
                                console.log("PW:", password)
                                handleLogin();
                            }
                        }}
                    >
                    </IonInput>

After struggling with this for about 30 minutes, I just replaced the IonInput with a generic html input, and now it works.

                    <label htmlFor="password">Password:</label>
                    <input
                        ref={passwordFieldRef}
                        value={password}
                        type={"password"}
                        onChange={(e: any) => {
                            console.log("CHANGE TRIGGERED")
                            setPassword(e.target.value!)
                            console.log("PW:", password)
                        }}
                        onKeyDown={(e) => {
                            if (e.key === "Enter") {
                                console.log("PW:", password)
                                handleLogin();
                            }
                        }}
                    >
                    </input>

If I did something really dumb please correct me, but this seems like an Ionic bug and what I don’t understand is why IonInput would even be messing with the browser api for onChange? (note, within IonInput, I tried using the normal onChange instead of onIonChange and still the same bug)

1 Like

Create reproducible error in a stackblitz project and post the link.

“Reproduce it on stackblitz” is always the response, but the most recent ionic-react version I can find to fork from is still on v5. And there’s tons of breaking changes from v5 to v7. If someone can provide an updated stackblitz for me to fork from I’ll try to reproduce, but I don’t really have time otherwise :sweat_smile:

Reason being is cause more than likely its a user error and not the framework. There are daily endless post about simple things like this one and people don’t like to read docs, just ask questions without researching first.

So in order to rule out the framework as the issue, the OP should create a project in stackblitz that can reproduce the error they get. This way it can weed out the lazy people. So since YOU don’t have the time to create a demo of YOUR issue, then WE don’t have the time to help you! :slightly_smiling_face:

How I wish :sweat_smile:

Sure, in theory. But I’m not lazy - it’s easier for me to ignore or work around the issue rather than try to fix it. I’d hope someone more invested in the framework would setup an ionic-react v7 repo for me to fork. I’ll spend 30 minutes on this, but I’m ****ing swamped and I don’t have time to try to solve dependency issues in stackblitz. Let it be a bug then, I don’t care.

2 Likes

I wonder if this is related to @ionChange not fired in ionic v7 - #7 by twestrick :thinking: I never created a bug report because I don’t use it so never got around to submitting one.

2 Likes

Could be :thinking: It seems very similar. In that case if I understand it doesn’t fire on de-focus? And here it only fires on de-focus lol.

Here is a stackblitz anyways. You can see in the console logs that the IonInput only updates on de-focus, whereas the normal html input updates on every key press. This is a bug because the expected behavior is the same between them. It’s causing a problem for me because I have the enter key programmed to log the user in, so the password field never gets de-focused (and thus no password).

1 Like

Per the documentation, you need to use onIonInput to update values of an IonInput as the user types. onIonChange only fires when the element loses focus. This was a breaking change in Ionic v7.

1 Like

To add, Ionic is following the HTML spec.

Per MDN change event:

  • When the element loses focus after its value was changed: for elements where the user’s interaction is typing rather than selection, such as a <textarea> or the text, search, url, tel, email, or password types of the <input> element.

Here is a StackBlitz with raw HTML. onchange is only fired when the input loses focus. I don’t know anything about React, but it must be overriding the change event on normal input elements.

did you try onIonInput? seems to work for me if I understand your issue

Ok. So I did read the breaking change, but I understood it differently.

ionChange is no longer emitted when the value of ion-input is modified externally. ionChange is only emitted from user committed changes, such as typing in the input and the input losing focus

I’m interpretting this as ionChange should fire when the user types. “ionChange is only emitted from user committed changes, such as typing”. I am a user typing, and ionChange isn’t emitting.

In either case, as shown in the stackblitz I posted…

IonInput with onIonChange
behaves differently from
input with onChange

Whether it’s a documentation issue or whatever the functionality is supposed to be… I’d expect their behavior to match.

Yes, it’s a workaround for the bug.

That’s really interesting actually. I can’t find anything about React overriding basic html inputs, but this is a really common paradigm and seems to be the case. How strange!

I just looked and found it. See the React docs here.

onChange: An Event handler function. Required for controlled inputs. Fires immediately when the input’s value is changed by the user (for example, it fires on every keystroke). Behaves like the browser input event.

So React is treating onchange as oninput which doesn’t follow the HTML spec.

EDIT
For onInput it says:

onInput: An Event handler function. Fires immediately when the value is changed by the user. For historical reasons, in React it is idiomatic to use onChange instead which works similarly.

I seeee. Also just saw this. Learning stuff every day :grin:

So that explains what’s happening. The question then…

  1. The upgrade documentation is definitely wrong - correct?

  2. And at least for Ionic-React, this should also be considered a bug - correct?

so is this about finding a solution or opening an issue? Not sure what is going on here and just trying to get you help… your response to me seems kinda off

Sorry for being terse, I am kind of frustrated :sweat_smile: it is more about fixing the bug. I have a workaround in place.

I think the breaking documentation is correct, maybe just not the clearest.

I read “such as typing in the input and the input losing focus” that the user has both typed AND the input has lost focus. The bullet point right after does clarify.

If your application requires immediate feedback based on the user typing actively in the input, consider migrating your event listeners to using ionInput instead.

In regards to whether it is a bug for Ionic React, I would say not as the Ionic team changed it across the board for all frameworks. But, @ldebeasi is the one to say for sure.

1 Like

Oh yeah, I was really confused by this in React as well. To break it down:

Browser Default Input Behavior

  • The input event fires for each keystroke in an input
    The change event fires when the value of the input is committed (i.e. someone types into the input and the input loses focus)

Ionic Framework Input Behavior

  • The ionInput event follows the browser’s input event behavior
  • The ionChange event follows the browser’s change event behavior.

In other words, Ionic matches the native browser behavior.

React Input Behavior (without Ionic)

React modifies how the change event behaves when using a native <input />. You can read more on Bug: manually created 'change' events via new Event() don't trigger React event handlers · Issue #19846 · facebook/react · GitHub, but the change event in React essentially follows the browser’s default input event behavior.

As a result, there is going to be a behavior difference between Ionic React and React. However, this is due to how React has modified the input event behavior.

edit: Here’s a bit more info on the React behavior: Document how React's onChange relates to onInput · Issue #3964 · facebook/react · GitHub

4 Likes