Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useBreakpoint throws TypeError: queryList.addEventListener is not a function #4962

Closed
4 tasks done
MoistJohn opened this issue Jan 28, 2024 · 4 comments
Closed
4 tasks done
Labels
iOS An issue or a feature-request for an iOS platform pending-maintainer-response Issue is pending response from an Amplify UI maintainer

Comments

@MoistJohn
Copy link

Before creating a new issue, please confirm:

On which framework/platform are you having an issue?

React

Which UI component?

Authenticator

How is your app built?

Vite

What browsers are you seeing the problem on?

Chrome, Safari

Which region are you seeing the problem in?

No response

Please describe your bug.

Using these dependencies:

"dependencies": {
    "@aws-amplify/ui-react": "^6.1.0",
    "@vitejs/plugin-legacy": "^5.3.0",
    "aws-amplify": "^6.0.10",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "terser": "^5.27.0",
    "typescript": "^5.3.3",
    "vite": "^5.0.11"
  },

With this vite configuration:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import legacy from "@vitejs/plugin-legacy";

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react(), legacy()],
  build: {
    minify: false,
  },
  base: "./",
});

When running on older iOS devices:

  • iPhone 11
  • iPhone 11 Pro Max
  • iPhone XR
  • iPad mini
  • iPad Air

an error TypeError: queryList.addEventListener is not a function. (In 'queryList.addEventListener("change", handleMediaChange)', 'queryList.addEventListener' is undefined) is thrown when trying to render <Authenticator>

What's the expected behaviour?

The Authenticator component should support older devices.

Help us reproduce the bug!

Attempt to render the component on any of the following, with Safari or Chrome

  • iPhone 11
  • iPhone 11 Pro Max
  • iPhone XR
  • iPad mini
  • iPad Air

Code Snippet

// Put your code below this line.
export function App() {
  const { authStatus, signOut } = useAuthenticator((context) => [
    context.authStatus,
  ]);

  return (
    <Authenticator hideSignUp={true}>
        <InternalElement/>
    </Authenticator>
}

The following snippet is the un-minified compiled JS code of the useBreakpoint hook that the Authenticator uses:

const useBreakpoint = ({ breakpoints: breakpoints2, defaultBreakpoint }) => {
  const supportMatchMedia = typeof window !== "undefined" && typeof window.matchMedia !== "undefined";
  const matchMedia = supportMatchMedia ? window.matchMedia : null;
  const mediaQueries = reactExports.useMemo(() => getMediaQueries({ breakpoints: breakpoints2 }), [breakpoints2]);
  const [breakpoint, setBreakpoint] = reactExports.useState(defaultBreakpoint);
  const updateBreakpoint = reactExports.useCallback((matches2, breakpoint2) => {
    if (matches2) {
      setBreakpoint(breakpoint2);
    }
  }, [setBreakpoint]);
  useIsomorphicEffect(() => {
    if (!matchMedia)
      return;
    const unsubscribeList = mediaQueries.map(({ query, breakpoint: breakpoint2 }) => {
      const queryList = matchMedia(query);
      updateBreakpoint(queryList.matches, breakpoint2);
      const handleMediaChange = (event) => {
        if (event.matches) {
          setBreakpoint(breakpoint2);
        }
      };
      queryList.addEventListener("change", handleMediaChange);  // <=== This throws the error
      return () => queryList.removeEventListener("change", handleMediaChange);
    });
    return () => {
      unsubscribeList.forEach((unsubscribe) => unsubscribe());
    };
  }, [breakpoints2, setBreakpoint, matchMedia, mediaQueries]);
  reactExports.useDebugValue(breakpoint, (breakpoint2) => breakpoint2);
  return breakpoint;
};

When I changed the snippet with the following, the component seems to work:

      if (typeof queryList.addListener === 'function') {
        queryList.addListener(handleMediaChange);
      } else {
        queryList.addEventListener("change", handleMediaChange);
      }
      return () => {
          if (typeof queryList.removeListener === 'function') {
              queryList.removeListener(handleMediaChange);
          } else {
            queryList.removeEventListener("change", handleMediaChange);
          }
      }

Console log output

TypeError: queryList.addEventListener is not a function. (In 'queryList.addEventListener("change", handleMediaChange)', 'queryList.addEventListener' is undefined)

Additional information and screenshots

No response

@github-actions github-actions bot added the pending-triage Issue is pending triage label Jan 28, 2024
@esauerbo esauerbo added iOS An issue or a feature-request for an iOS platform being-investigated and removed pending-triage Issue is pending triage labels Jan 29, 2024
@esauerbo
Copy link
Contributor

Hi @MoistJohn thanks for creating this issue. I'm looking into this and will try to reproduce the behavior.

@esauerbo
Copy link
Contributor

esauerbo commented Jan 29, 2024

@MoistJohn which version of Safari/chrome are you seeing this error with, and which iOS?

@hbuchel
Copy link
Contributor

hbuchel commented Feb 7, 2024

Hi @MoistJohn since addListener() is deprecated for major browsers and they have supported addEventListener as used in our use case for quite some time now (in Safari, at least 4 years since from what I can find) we don't have plans on adding support for this.

@hbuchel hbuchel closed this as not planned Won't fix, can't repro, duplicate, stale Feb 7, 2024
@Oram
Copy link

Oram commented Dec 26, 2024

To anyone struggling, this monkey patching solved the problem:

const originalMatchMedia = window.matchMedia;
window.matchMedia = (query) => {
  const originalResults = originalMatchMedia(query);
  if (!originalResults.addEventListener) {
    originalResults.addEventListener = (type, callback) => {
      return originalResults.addListener(callback);
    };
  }
  if (!originalResults.removeEventListener) {
    originalResults.removeEventListener = (type, callback) => {
      return originalResults.removeListener(callback);
    };
  }
  return originalResults;
};

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify UI maintainer label Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
iOS An issue or a feature-request for an iOS platform pending-maintainer-response Issue is pending response from an Amplify UI maintainer
Projects
None yet
Development

No branches or pull requests

5 participants