2

I am currently trying to use TailWindElements-React in Clojure Script. In JS an example would look like this:

import React, { useState } from "react";
import { TECollapse, TERipple } from "tw-elements-react";

export default function App(): JSX.Element {
  const [show, setShow] = useState(false);

  const toggleShow = () => setShow(!show);

  return (
    <>
      <TERipple rippleColor="light">
        <a
          className="inline-block rounded bg-primary mr-2 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)] 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)]"
          role="button"
          onClick={toggleShow}
        >
          Link
        </a>
      </TERipple>
      <TERipple rippleColor="light">
        <button
          type="button"
          className="inline-block 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)] 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)]"
          onClick={toggleShow}
        >
          Button
        </button>
      </TERipple>

      <TECollapse show={show}>
        <div className="block rounded-lg bg-white p-6 shadow-lg dark:bg-neutral-700 dark:text-neutral-50">
          Some placeholder content for the collapse component. This panel is
          hidden by default but revealed when the user activates the relevant
          trigger.
        </div>
      </TECollapse>
    </>
  );
}

Now if I want to use these classes I write

(:require ["tw-elements-react" :refer (TECollapse TERipple)])

and then

[:> TERipple
  [:div ... ]
]

Doing so compiles without a problem but in the browser console I get

Warning: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.

and

Uncaught TypeError: resolveDispatcher() is null

If I do not wrap the div with TERipple the code works fine.

Is anyone of you able to make this work? I am using shadow-cljs version 2.28.6.

Edit: I decontextualized my problem and tried to build a minimal working example. I used the leiningen template clojure lein new re-frame test +10x and then upgraded the shadow-cljs version to 2.28.6. Then I installed TWE-React and TW. The only thing I altered from the template was that I added a button and wrapped it within the TERipple component. Here is my views.cljs:

(ns test.views
  (:require
   [re-frame.core :as re-frame]
   [test.subs :as subs]
   ["tw-elements-react" :refer (TECollapse TERipple)]))

(defn main-panel []
  (let [name (re-frame/subscribe [::subs/name])]
    [:div
     [:h1
      "Hello from " @name]
     [:> TERipple
      [:button.bg-red "Press me"]]]))

The error remains the same.

6
  • Your JS example is substantially longer than the CLJS snippet. Do you actually also use the useState hook as the JS example? Commented May 14, 2024 at 17:11
  • You are right, no I did not. How would that look like? Commented May 15, 2024 at 13:02
  • Just trying to rule out the hook warning actually coming from your code and having nothing to do with tw-elements-react. Kinda hard to give any kind of answer with only partial code. Commented May 15, 2024 at 13:27
  • Well, if I omit the [:f> TWRipple ... ] it works fine. Edit: Ah sorry, I misunderstood you. Yeah I dont know how to figure this out. I am too unfamiliar with react to properly translate it myself. I think I could profit from a working example using TWE in clojurescript but I could not find any and the creators of TWE are unfamiliar with CLJS and therefore were also unable to help. Commented May 15, 2024 at 13:32
  • That doesn't mean much., since it just maybe doesn't run into the problem code. Did you verify that none of the things the warning mentions are true for your setup? Commented May 15, 2024 at 13:37

2 Answers 2

3
  1. You might have mismatching versions of React and the renderer (such as React DOM)

This is the problem here. tw-elements-react depends on version "^18.2.0" of react+react-dom, but the default generated package depends on react+react-dom version "17.0.2". This leads npm to install and use both. Thus you end up with the warnings above.

I verified this by doing a shadow-cljs build report and finding that there were indeed two separate react+react-dom versions in the build.

Running npm install [email protected] [email protected] fixes the TERipple issue.

Sign up to request clarification or add additional context in comments.

1 Comment

You are my knight in shining armor, thank you very much!
1

I think you need to use a function component since "[React] Hooks can only be called inside of the body of a function component". Something like this:

[:f> TERipple body]

4 Comments

The wrapper is not required, just [:f> TERipple ...] should be fine.
Thank you, however, this results in the following error in the browser console: Uncaught Error: Assert failed: Expected something callable, not #js {"$$typeof" #object[Symbol(react.forward_ref)], :render #object[Function], :reagent-compiler2 #js {"$$typeof" #object[Symbol(react.memo)], :type #object[Function], :compare #object[reagent$impl$component$functional_render_memo_fn]}} (clojure.core/ifn? f)
that #js part indicates a regular react element, not a function. So, [:> TERipple ...] should be fine. Need more code for context.
I provided a minimal working example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.