Skip to content

SelectPanel2 Optimization: Do not add and remove keydown listener for escape key on every render #4581

Description

@bwittenberg

Description

SelectPanel2.SelectPanel will call dialogEl.removeEventListener and dialogEl.addEventListener on every render, because the call to React.useEffect is not passed an array of dependencies at this callsite: https://github.com/primer/react/blob/main/packages/react/src/drafts/SelectPanel2/SelectPanel.tsx#L195

The React docs describe this behavior here: https://react.dev/reference/react/useEffect#parameters

If you omit this argument, your Effect will re-run after every re-render of the component.

I suspect the dependency array was an accidental omission.

Why am I filing this bug/optimization issue?

I was interested in making a contribution to this repository, and I wanted to start with a small, low impact change. Select components are interesting to me, so I began reviewing the component to look for ways to help, and I came across this as a potential optimization. It's a nitpick, and may not have any real impact on user performance, so I understand if the maintainers want to close without addressing.

Steps to reproduce

The following test case will fail for me when I added to https://github.com/primer/react/blob/main/packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsx.

Note: This is a fairly "white box" test and relies on implementation details. I find that these kind of tests are useful to check performance optimizations, but the tradeoff is that the tests are more brittle.

// packages/react/src/drafts/SelectPanel2/SelectPanel.test.tsxit('should not call addEventListener on each render',async()=>{constcontainer=render(<SelectPaneltitle="title">child</SelectPanel>)constdialogEl=container.getByRole('dialog',{hidden: true})constaddEventListenerSpy=jest.spyOn(dialogEl,'addEventListener')constremoveEventListenerSpy=jest.spyOn(dialogEl,'removeEventListener')container.rerender(<SelectPaneltitle="title">child</SelectPanel>)expect(addEventListenerSpy).not.toHaveBeenCalled()expect(removeEventListenerSpy).not.toHaveBeenCalled()})

Version

v36.17.0

Browser

No response

Activity

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