Fork me on GitHub
#reagent
<
2023-03-15
>
Martin Mariano14:03:29

Are there any known issues using Hooks and reagent form-3 components? When transforming this, a form-1 component:

(defn dnd-marketplace-attr
  [attr-id {:keys [plain? match? extra-class] :as _opts} children]
  (let [[_ drop] (useDrop (clj->js {:accept  candidate-attribute-type
                                    :drop    (fn [drag-item]
                                               (rf/dispatch-sync [::cane/link-attributes-by-dnd attr-id drag-item]))
                                    :collect (fn [^js monitor]
                                               {:isOver  (.isOver monitor)
                                                :canDrop (.canDrop monitor)})}))]
    [:div {:ref drop}
     [outer-panel (merge (when extra-class {:extra-class extra-class})
                         {:padding {:x :lg :y :sm}})
      [grid {:columns 6}

       [:<>
        (when-not plain?
          [box-icon match? :start :marketplace])
        [v-box {:extra-class "col-span-5"} children]]]]]))
To a form-3 component:
(defn dnd-marketplace-attr
  [attr-id {:keys [plain? match? extra-class] :as _opts} children]
  (let [[_ drop] (useDrop (clj->js {:accept  candidate-attribute-type
                                     :drop    (fn [drag-item]
                                                (rf/dispatch-sync [::cane/link-attributes-by-dnd attr-id drag-item]))
                                     :collect (fn [^js monitor]
                                                {:isOver  (.isOver monitor)
                                                 :canDrop (.canDrop monitor)})}))]
     (r/create-class
      {:display-name "dnd-marketplace"

       :component-did-mount
       (fn [this]
         (rf/dispatch [::cane/toggle-screen {:id   attr-id
                                             :kind :marketplace}]))
       :component-will-unmount
       (fn [this]
         (rf/dispatch [::cane/toggle-screen {:id   attr-id
                                             :kind :marketplace}]))

       :reagent-render
       (fn [attr-id {:keys [plain? match? extra-class] :as _opts} children]
         [:div {:ref drop}
          [outer-panel (merge (when extra-class {:extra-class extra-class})
                              {:padding {:x :lg :y :sm}})
           [grid {:columns 6}

            [:<>
             (when-not plain?
               [box-icon match? :start :marketplace])
             [v-box {:extra-class "col-span-5"} children]]]]])})))
The component gets rendered, but when interacting with the component by clicking and dragging (the hook is from the react-dnd lib) an error of a hook early return pops up and the application crash. Mind that this only happens on the form-3 component, and form-1 works correctly. Also the component is being rendered with the :f> shortcut. Am I missing something here? Hooks are from the react-dnd library.

p-himik14:03:29

Hooks are only for function components. A form-3 component is a class component.

Martin Mariano14:03:12

Do you know of any way to avoid this? Lifecycle methods would be convenient for the situation I'm dealing with.

p-himik14:03:53

Lifecycle methods can be replaced with hooks as well. React has a few built into it specifically for that.

🙌 2
Martin Mariano15:03:51

Thanks a ton! Just found out about useEffect. https://reactjs.org/docs/hooks-effect.html#recap

👍 2
aaelony15:03:26

My google searches are pointing to blogs from 2015 or earlier. What libraries or techniques are currently recommended for authenticating users and having a separate experience for users that are anonymous versus logged-in in a reagent shadow-cljs app?

p-himik15:03:40

Curious - what are the blogs that you've found? I've had to implement it for 2 very different websites. The approaches dictated by the business needs ended up being completely different but also very straightforward - so much so that it's hard for me to imagine that a generic technique or a lib should or can exist.

aaelony16:03:49

@U2FRKM4TW I am seeking input, don't want to bias the answers, thanks. 😉

p-himik16:03:50

I have already provided an answer that I could've - as I said, I'm just curious.

aaelony16:03:52

No idea, here that's why I ask. Maybe Buddy-Auth? Friend? no clue -- beyond these.

p-himik16:03:18

Oh, so that "and" is not central to the question? I thought that "and having a separate experience" was the crux of the question. Friend is archived with open issues and a note in its README saying that it shouldn't be used. I've been using Buddy for quite some time - perfectly satisfies my needs. In general for questions such as this, things like https://www.juxt.pro/radar/ are very helpful, especially when they describe their reasoning. As you can see, they mention Buddy in the "adopt" section.

👍 2
aaelony17:03:57

Again, Buddy is from 2015 or earlier and is seeking new maintainers. I would expect there are libraries in the js or node space that people use. Was hoping for those kind of answers... Perhaps others roll their own.

p-himik17:03:04

Perhaps the initial question could be improved? You mentioned Reagent and shadow-cljs. How are those relevant to authentication? How is UI in general relevant to authentication? You mentioned Buddy and Friend, but those have nothing to do with UI. If your app is not something with special needs (like having a distributed database or lack of persistence or something else), then one of the oldest and simplest techniques still perfectly fits the bill. Not according to me, but according to at least some IT security experts online. The technique is to simply generate, store, and check session ID (also stored on the client side in a secure cookie) + CSRF token (stored in UI state). What exactly to do on the backend depends on the specifics of your app. But you need just few things - being able to generate and store 2 numbers and associate them with a user ID, and some server endpoints to create (with password checking) and delete relevant session records. What exactly to do on the frontend also depends on the specifics of your app. But all you need is to store the "authenticated" flag along with the CSRF token (in state, not in cookies) and to be able to issue login/logout requests to those aforementioned endpoints. That's pretty much it. Since every single of those things depends on what you're already using in your app, it doesn't seem to make much sense to invent any library here. Otherwise it'll either be an "authentication library for apps that use PostgreSQL, Ring, re-frame, kee-frame, re-form, and Tailwind CSS" or something that has more configuration flags than parameters.

aaelony18:03:37

fair enough. Thanks for the answer

👍 2
hifumi12318:03:10

I would say it depends on the backend and how their strategy for authentication and authorization is. My situation requires me to use keycloak-js, for instance. It exposes functions for performing OAuth flows, refreshing tokens, etc. It’s also capable of silently performing SSO checks so that I can tell whether a user is logged in or not, and act accordingly I use this library because Keycloak is the IdP we happen to be using, and the official JavaScript adapter is easy to use from CLJS and does everything I need.

🔥 2
p-himik19:03:49

Note that it's very different from what a regular app would require. Not everybody needs a full-on IAM, let alone a third-party solution that complects things.

👍 2
hifumi12319:03:56

also I wouldn’t recommend pulling in this library if you use it exclusively from CLJS since you’ll be downloading like 30 java dependencies that you ultimately wont use I found it more useful to use keycloak-js directly, though the documentation of that library does give you a good start on how to authenticate with a keycloak server from cljs. You’ll also find that the frontend namespace is a very thin wrapper

👍 2