TW-Elements icon indicating copy to clipboard operation
TW-Elements copied to clipboard

[Dropdown] [Not working properly in reactStrictMode: true]

Open navidmadannezhad opened this issue 2 years ago • 4 comments

Describe the bug Hi! I noticed when we are setting reactStrictMode: true in our nextjs application, tw-elements dropdown is not working properly

To Reproduce Steps to reproduce the behavior:

  1. Create a new nextjs project
  2. Set reactStrictMode: true
  3. use dropdown in where ever you want and see what is happening

Expected behavior Dropdown opens when I click on the dropdown button, and gets closed when I click again or click somewhere outside the dropdown container

Actual behavior Dropdown opens, and gets closed immediately, like after 50ms

Show your code page.tsx:

'use client'

import {
  Dropdown,
  Ripple,
  initTE,
} from "tw-elements";
import { useEffect } from 'react';

export default function Home() {
  useEffect(() => {
      initTE({ Dropdown, Ripple });
  }, [])

  return (
    <>
      <div className="relative" data-te-dropdown-ref>
          <button
              className="flex items-center whitespace-nowrap rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] motion-reduce:transition-none dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              type="button"
              id="dropdownMenuButton1"
              data-te-dropdown-toggle-ref
              aria-expanded="false"
              data-te-ripple-init
              data-te-ripple-color="light">
              Dropdown button
              <span className="ml-2 w-2">
              <svg
                  xmlns="http://www.w3.org/2000/svg"
                  viewBox="0 0 20 20"
                  fill="currentColor"
                  className="h-5 w-5">
                  <path
                  fill-rule="evenodd"
                  d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
                  clip-rule="evenodd" />
              </svg>
              </span>
          </button>
          <ul
              className="absolute z-[1000] float-left m-0 hidden min-w-max list-none overflow-hidden rounded-lg border-none bg-white bg-clip-padding text-left text-base shadow-lg dark:bg-neutral-700 [&[data-te-dropdown-show]]:block"
              aria-labelledby="dropdownMenuButton1"
              data-te-dropdown-menu-ref>
              <li>
              <a
                  className="block w-full whitespace-nowrap bg-transparent px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-neutral-100 active:text-neutral-800 active:no-underline disabled:pointer-events-none disabled:bg-transparent disabled:text-neutral-400 dark:text-neutral-200 dark:hover:bg-neutral-600"
                  href="#"
                  data-te-dropdown-item-ref
                  >Action</a
              >
              </li>
              <li>
              <a
                  className="block w-full whitespace-nowrap bg-transparent px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-neutral-100 active:text-neutral-800 active:no-underline disabled:pointer-events-none disabled:bg-transparent disabled:text-neutral-400 dark:text-neutral-200 dark:hover:bg-neutral-600"
                  href="#"
                  data-te-dropdown-item-ref
                  >Another action</a
              >
              </li>
              <li>
              <a
                  className="block w-full whitespace-nowrap bg-transparent px-4 py-2 text-sm font-normal text-neutral-700 hover:bg-neutral-100 active:text-neutral-800 active:no-underline disabled:pointer-events-none disabled:bg-transparent disabled:text-neutral-400 dark:text-neutral-200 dark:hover:bg-neutral-600"
                  href="#"
                  data-te-dropdown-item-ref
                  >Something else here</a
              >
              </li>
          </ul>
      </div>
    </>
  )
}

next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
    reactStrictMode: true
}

module.exports = nextConfig

tailwind.config.js:

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: "class",
  content: [
    './src/pages/**/*.{js,ts,jsx,tsx,mdx}',
    './src/components/**/*.{js,ts,jsx,tsx,mdx}',
    './src/app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {
      backgroundImage: {
        'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
        'gradient-conic':
          'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
      },
    },
  },
  plugins: [require("tw-elements/dist/plugin.cjs")],
}

navidmadannezhad avatar Jun 02 '23 04:06 navidmadannezhad

Did you solve this issue?

xzegga avatar Jun 02 '23 23:06 xzegga

@xzegga not yet, I faced this issue on a developing project. I wondered maybe it's some kind of libraries interference so I tested it on a fresh next project, and well that was the result.

navidmadannezhad avatar Jun 03 '23 09:06 navidmadannezhad

Same issue here. I think the problem is related to multiple initTE() executions, caused by multiple useEffect() executions. It seems that, internally, initTE() does not check if TE has been already initialized, so if it is invoked multiple times, it attaches the listeners multiple times. In the case of the dropdown, it triggers multiple time the toggle listener which means opening and immediately closing the dropdown.

I solved with a combination of the solution mentioned in #1615 and an internal check:

  const teInitialized = useRef(false)

  useEffect(() => {
    setTimeout(() => {
      if (!teInitialized.current) {
        console.debug(`Tailwind Elements initialized`)
        initTE({ Dropdown })
      }
      teInitialized.current = true
    }, 1000)
  }, []) 

keadex avatar Jun 11 '23 21:06 keadex

Hi, yes apparently something went wrong inside initTE and the array that is supposed to include the already inited elements, do not receive them. We are going to fix this, sorry for the inconvenience.

juujisai avatar Jun 12 '23 11:06 juujisai