Skip to content

onFocusIn/onFocusOut events #6410

Closed
Closed

Description

@sophiebits

Like mouse enter/leave, these are almost always what you want, not the onFocus and onBlur events we currently expose. I run into this semi-frequently when actually doing product work. We should add them.

Activity

  1. jimfb commented on Apr 5, 2016

    @jimfb
    Contributor

    FWIW, I agree with you. People know about focusin/focusout, and so we should just make them work, despite the fact that they would map to the exact same event handler we use for focus/blur.

    However, last time this was discussed, we opted to not do this (#6226) and decided to warn instead (https://github.com/facebook/react/pull/6296/files).

    I'd be fine with reversing this decision if you can get the momentum within the team.

  2. sophiebits commented on Apr 6, 2016

    @sophiebits
    ContributorAuthor

    It looks like it was decided against because of an incorrect claim that they're indistinguishable from onFocus/onBlur. onFocusIn/onFocusOut is different in that when moving focus between two children of an element, neither event fires on the container.

  3. sophiebits commented on Apr 6, 2016

    @sophiebits
    ContributorAuthor

    Doing it properly means adapting the logic in EnterLeaveEventPlugin and isn't as simple as adding it to SimpleEventPlugin.

  4. gaearon commented on Apr 6, 2016

    @gaearon
    Collaborator

    Ah, that makes sense. Thanks for explaining!

    Adding “good first bug” here. Note @spicyj’s comments: they need to behave like onMouseEnter and onMouseLeave. You’ll want to look at EnterLeaveEventPlugin.

  5. fyodoriv commented on Apr 6, 2016

    @fyodoriv

    I'd like to work on it if nobody minds. Enough with the tests, time to add real source code!

  6. fyodoriv commented on Apr 7, 2016

    @fyodoriv

    Hey @gaearon @spicyj apparently there is a confusion here, let me explain.
    mouseover and mouseout bubble up. mouseenter and mouseleave don't bubble up. Corresponding React event handlers work the same as native events - awesome.

    Native focus and native blur events don't bubble. Corresponding React event handlers onFocus and onBlur do bubble - dun dun dun.

    Native focusin and native focusout events do bubble. React events for these should be implemented and bubble too.

    Here is a jsfiddle I made to display this. Checked in Chrome only, as since MDN documentation states that this is intended behavior then I believe it should be the same in other browsers.

    If I am right about this (please correct me if I am wrong), then the following should be done:
    0. Warnings about onFocusIn/onFocusOut should be removed (obviously).

    1. Currect React onFocus should be renamed to onFocusIn; onBlur - to onFocusOut as they currently work the same as native onFocusIn and onFocusOut work - they bubble.
    2. onFocus and onBlur event listeners should be implemented in React - which will not bubble.
  7. sophiebits commented on Apr 7, 2016

    @sophiebits
    ContributorAuthor

    Hmm, that sounds plausible. Thanks for the correction. Kinda annoying that we'll end up renaming these for people but maybe it's for the best.

  8. fyodoriv commented on Jun 5, 2016

    @fyodoriv

    Hey, unfortunately, I cannot invest time in this right now and I must pause. I have added onFocusIn/Out by mimicing onFocus/onBlur but I am having issues with changing onFocus/onBlur so they don't bubble.
    I don't want to slow down the awesomeness of React so if anyone wants to invest into this issue - please do. If nobody does - I will get back to it when I have more time. Good luck!

  9. jimfb commented on Jun 5, 2016

    @jimfb
    Contributor

    but I am having issues with changing onFocus/onBlur so they don't bubble.

    Do we want them to not bubble? We had previously said that all events bubble. I'm fine with whatever, so I'll leave that decision to @spicyj since he has the most situational awareness here.

  10. mrscobbler commented on Jun 13, 2016

    @mrscobbler
    Contributor

    Since this is tagged as a good first bug I thought I'd take a stab at this. Let me know if you're still working on it @cbrwizard !

  11. mrscobbler commented on Jun 13, 2016

    @mrscobbler
    Contributor

    I did a little more investigating and it looks like focusin and focusout events are not supported by Firefox. Is this still something you want to implement if all browsers don't support it? See here: https://developer.mozilla.org/en-US/docs/Web/Events/focusin and here: https://bugzilla.mozilla.org/show_bug.cgi?id=687787

  12. jimfb commented on Jun 13, 2016

    @jimfb
    Contributor

    @mrscobbler It should be possible to polyfill the event on any browsers that don't natively support it. We do this with several events that are not supported on particular browsers.

  13. mrscobbler commented on Jun 13, 2016

    @mrscobbler
    Contributor

    Ok! Good to know.

  14. 42 remaining items

  15. added a commit that references this issue on Feb 4, 2020
  16. gaearon commented on Jul 24, 2020

    @gaearon
    Collaborator

    Coming back to this thread, I'm not sure what is being asked here. If I understand correctly:

    • People are asking to support onFocusIn and onFocusOut events.
    • However, React already bubbles onFocus and onBlur events, which is analogous to the browser behavior for onFocusIn and onFocusOut.

    I'm not sure that everybody who commented this actually have the same request in mind. If this issue is still relevant to you, can you please restate what you are asking? Taking into account that "add onFocusIn" doesn't mean much because React onFocus already behaves like onFocusIn. Thanks!

  17. tilgovi commented on Jul 24, 2020

    @tilgovi

    I'm not sure that everybody who commented this actually have the same request in mind. If this issue is still relevant to you, can you please restate what you are asking?

    I would have to think pretty hard to remember the case that motivated me to subscribe to this and to link it from #13525. I believe I had a case where I thought it would be nice if onFocus and onBlur did not bubble, but behaved like the browser events. Then, having onFocusIn and onFocusOut would be useful because they do bubble.

  18. craigkovatch commented on Jul 24, 2020

    @craigkovatch

    @gaearon my request is that React internally listen to focusin/focusout rather than focus/blur, because there is information missing in the latter (e.g. relatedTarget, see #6410 (comment)). But keep the same bubbling behavior as now.

  19. tilgovi commented on Jul 24, 2020

    @tilgovi

    Ahh, yes, @craigkovatch might actually be onto what was causing me trouble.

  20. gaearon commented on Jul 24, 2020

    @gaearon
    Collaborator

    I believe I had a case where I thought it would be nice if onFocus and onBlur did not bubble, but behaved like the browser events.

    This makes sense. The workaround is to check e.target === e.currentTarget for those cases. Maybe someday we can change this.

    my request is that React internally listen to focusin/focusout rather than focus/blur, because there is information missing in the latter

    All right, this is good to know. We've actually made that exact change on master so it should go out in 17.

  21. tilgovi commented on Jul 24, 2020

    @tilgovi

    Maybe someday we can change this.

    Yeah, that's why I brought it up in #13525 (comment) in the context of other breaking changes to align with how DOM events work. From that issue's description around changes to onChange and onInput (emphasis mine):

    It has been confusing that React uses a different event name for what's known as input event in the DOM. While we generally avoid making big changes like this without significant benefit, in this case we also want to change the behavior to remove some complexity that's only necessary for edge cases like mutating controlled inputs. So it makes sense to do these two changes together, and use that as an opportunity to make onInput and onChange work exactly how the DOM events do for uncontrolled components.

  22. tilgovi commented on Jul 24, 2020

    @tilgovi

    In summary, I don't have a specific need and there are workarounds, but it could be nice to align with the DOM if that means fewer surprises. Of course, there's an argument to be made that the DOM events are surprising or unintuitive, but I'm not here to argue this either way. I'm all set! Glad to know relatedTarget is coming.

  23. jquense commented on Jul 24, 2020

    @jquense
    Contributor

    If we are asking for things what I want is focusenter/focusleave like we have for mouse and pointer events. Given that they aren't stanardized tho it's probably not a good fit for react dom

  24. gaearon commented on Jul 24, 2020

    @gaearon
    Collaborator

    Yeah most of our recent work has been to align closer with the DOM so this is not a good fit at this stage. But there's been parallel work on better accessibility primitives so I think maybe it's in that scope.

  25. gaearon commented on Aug 10, 2020

    @gaearon
    Collaborator

    In React 17, onFocus and onBlur internally listen to focusin and focusout.

    It seems like this addresses the core of this issue (#6410 (comment)). It's fair that maybe it would be nice to eventually rename them to align with the browsers (and possibly, add non-bubbling versions). Please feel free to raise new issues for these topics.

    To try React 17, install react@next and react-dom@next.

    Thanks to everyone for the very informative discussion!

  26. gaearon commented on Aug 11, 2020

    @gaearon
    Collaborator

    I made a small example demonstrating the current behavior based on #6410 (comment):

    https://codesandbox.io/s/strange-albattani-7tqr7?file=/src/App.js

    export default function App() {
      return (
        <div
          tabIndex={1}
          onFocus={(e) => {
            console.log("focusin (self or child)");
            if (e.currentTarget === e.target) {
              console.log("focus (self)");
            }
            if (!e.currentTarget.contains(e.relatedTarget)) {
              console.log("focusenter");
            }
          }}
          onBlur={(e) => {
            console.log("focusout (self or child)");
            if (e.currentTarget === e.target) {
              console.log("blur (self)");
            }
            if (!e.currentTarget.contains(e.relatedTarget)) {
              console.log("focusleave");
            }
          }}
        >
          <input />
          <input />
        </div>
      );
    }

    Hopefully this helps as a quick reference when you need to decide on which check to use.

    I think there's definitely room for improvement here but if we're talking about API changes, a detailed RFC would be the best way to move this forward: http://github.com/reactjs/rfcs

    I'll lock the discussion so people don't lose this canonical answer when coming from Google, but feel free to file new issues if something is unclear or not working.

  27. locked as resolved and limited conversation to collaborators on Aug 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions