reactjsfirefoxnext.jstailwind-cssheadless-ui

HeadlessUI has a Transition error message only in Firefox


I am using Tailwind and HeadlessUI in my Next JS project and am seeing this issue when trying to open the app only on Firefox

Unhandled Runtime Error

Error: A <Transition /> is used but it is missing a show={true | false} prop.

I think it would be coming from this code section below. But the confusing part is there is no issue opening it on Chrome and this is the same way that Transition is used in the HeadlessUI docs.

<Menu as="div" className="z-50">
  <Menu.Button className="flex items-center h-full">
    <>
      {user?.displayName && (
        <span className="pl-2">{user.displayName}</span>
      )}
      <UserCircleIcon
          className="w-10 h-10 p-2"
          aria-label="account options"
      />
    </>
  </Menu.Button>
  <Transition
    as={React.Fragment}
    enter="transition ease-out duration-100"
    enterFrom="transform opacity-0 scale-95"
    enterTo="transform opacity-100 scale-100"
    leave="transition ease-in duration-75"
    leaveFrom="transform opacity-100 scale-100"
    leaveTo="transform opacity-0 scale-95"
  >
    <Menu.Items className="absolute z-30 flex flex-col justify-start w-auto mt-4 origin-top-right rounded-md shadow-lg right-4 menu-items ring-1 ring-black ring-opacity-5 focus:outline-none bg-primary-background">
      {user ? (
        <>
          <Menu.Item>
            {({ active }) => (
              <MyLink href="/account" active={active}>
                Account settings
              </MyLink>
            )}
          </Menu.Item>
          <Menu.Item>
            {({ active }) => (
              <MyButton onClick={handleSignOut} active={active}>
                Logout
              </MyButton>
            )}
          </Menu.Item>
        </>
      ) : (
        <>
          <Menu.Item>
            {({ active }) => (
              <MyLink href="/login" active={active}>
                Sign In
              </MyLink>
            )}
          </Menu.Item>
          <Menu.Item>
            {({ active }) => (
              <MyLink href="/signup" active={active}>
                Create Account
              </MyLink>
            )}
          </Menu.Item>
        </>
      )}
    </Menu.Items>
  </Transition>
</Menu>

Tried using a HeadlesUI Transition as shown in the docs for a Menu component but it does not work in Firefox only


Solution

  • I found another error message that led to the solution:

    The above error occurred in the <ForwardRef> component:
    
    q<@webpack-internal:///./node_modules/@headlessui/react/dist/components/transitions/transition.js:17:6747
    CartPopup@webpack-internal:///./components/ui/cart/CartPopup.tsx:32:64
    LoadableImpl@webpack-internal:///./node_modules/next/dist/shared/lib/loadable.js:65:9
    div
    Layout@webpack-internal:///./components/Layout.tsx:33:17
    Home@webpack-internal:///./pages/index.tsx:17:19
    StoreProvider@webpack-internal:///./utils/Store.tsx:151:20
    FirebaseAuthProvider@webpack-internal:///./utils/firebase/firebaseAuth.tsx:60:20
    MyApp@webpack-internal:///./pages/_app.tsx:15:21
    ErrorBoundary@webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:20742
    ReactDevOverlay@webpack-internal:///./node_modules/next/dist/compiled/@next/react-dev-overlay/dist/client.js:8:23633
    Container@webpack-internal:///./node_modules/next/dist/client/index.js:70:24
    AppContainer@webpack-internal:///./node_modules/next/dist/client/index.js:216:20
    Root@webpack-internal:///./node_modules/next/dist/client/index.js:407:21
    
    React will try to recreate this component tree from scratch using the error boundary you provided, ErrorBoundary. 2
    

    I looked into my CartPopup component which is using Transition but it does use the show prop. It turned out to be the variable I was using to set the show prop to true | false was coming from my Store Context and for some reason was not getting a value on initial load. I changed it to be set to false by default when getting the state from useContext and it started working

    const { state, dispatch } = useContext(Store);
    const {
      cart: { cartItems, popUp = false } // Added '= false' to set popUp by default
    } = state;
    
    ...
    
    <Transition show={popUp} ... />