Fork me on GitHub
#reagent
<
2023-02-02
>
Michael00:02:10

How feasible is it to create a reagent project that's used as a react component library? Looks like the starter project is meant to be served as a web application.

hifumi12301:02:33

I would say “very feasible”. Take a look at re-com for some inspiration, although it uses re-frame for state management. Some workplaces also have their own UI library. Unfortunately that code is not open source 😐

Michael02:02:53

thanks. will take a look

p-himik09:02:41

If you mean creating a Reagent-using component that you will use from a plain React app, then it's not feasible. Re-com is a different thing - it's a Reagent library intended to be used from Reagent. Reagent even uses a custom render function to render the whole app - you can't tell a third-party app to somehow do that.

Rupert (All Street)10:02:46

You can expose clojurescript functions that can be called from JavaScript. With reagent these may need to start a new react context - so there will be a little overhead. Might be worth seeing if this is possible with uix or helix - but it might be the same. Another new/experimental/unfinished option is to use https://github.com/squint-cljs/squint to write JavaScript with Clojure like syntax.

Michael20:02:06

@U2FRKM4TW this is what I was trying to do. thanks for clearing it up

Michael09:02:32

@U2FRKM4TW sorry to ping you, but (concerning reagent-react interop) have you seen/tried https://cljdoc.org/d/reagent/reagent/1.0.0/doc/tutorials/interop-with-react#creating-react-components-from-reagent-components? I might give this a shot when I have time tomorrow but just wondering since all I've tried regarding reagent so far was just the default template they provide (which I think does the custom rendering stuff you were talking about)

p-himik09:02:44

That document describes how to create React components that you consume within the same Reagent app. It won't work for a library that needs to be embedded in a larger React-only app.

Izzy Lancaster04:02:16

Hello everyone! I'm a bit new to clojurescript and reagent, but familiar with web dev and react. I'm trying to figure out how to define a component that takes children for a tree-view component I'm building. I'm using & children in the component's parameters, but when this renders, Reagent complains about how "Every element in a seq should have a unique :key". Anyone know fix this? Here's the code for my tree-view component:

(defn tree-view-item [{:keys [label]} & children]
  [:li.tree-view-item 
   [:div 
    [:span.icon-container (if children "\u25B9" ())]
    [:span.label label]]
   (if children [:ul.tree-view-group children] ())])

p-himik09:02:05

You can use into:

(when children
  (into [:ul.tree-view-group] children))
(no need for empty lists)

Rupert (All Street)10:02:15

I think into is a good solution - another one is to add the :key metadata to each item e.g. (map-indexed (fn [i x] (with-meta x { :key (str "x" i)})) <data>)

p-himik10:02:51

Don't do that - don't use positional indices as keys. React describes why not in its documentation.

👍 2
Rupert (All Street)14:02:04

I think it's fine if you know they the items are not going to change (ie no additions/removals or re-ordering). map-indexed was just as a generic example - if you have a stable key then certainly use that first or the into code you mentioned.

Izzy Lancaster18:02:02

Thanks for the help, the when construct is really handy to know about. But I'm curious, why does it into work here?

Rupert (All Street)18:02:21

into is just adding the elements into the vector e.g. [:div "hello" "clojure" "world"] === (into [:div] (list "hello" "clojure" "world"))

Izzy Lancaster18:02:00

I understand that much. I don't understand why doing that solves the error

Rupert (All Street)18:02:48

When you have a list with keys or elements directly inside of vectors - reagent/react can efficiently work out which elements have changed and only re-render the ones that it needs to. If you have a list of 100s of elements and the first one is removed - it doesn't have to rerender all the others if you are using a list with keys.

p-himik19:02:35

> why doing that solves the error Reagent checks if something is a seq, and if it is, it issues that warning because, I assume, it doesn't want to try and figure out whether it's a lazy seq or not. Using into removes that lazy seq and makes all children known in advance. And Rupert's message describes why such a warning is useful. Although the commit in Reagent that introduced it makes me think that there were some issues besides performance.