Fork me on GitHub
#reagent
<
2024-03-10
>
agorgl21:03:20

Hello guys! I'm playing around with cljs/reagent/re-frame <-> js interop these days, and I've stumbled upon a problem that I cannot understand. I'm using tanstack/react-table like this:

(def columns
  [...
   {:accessorKey "status"
    :header "Status"
    :cell
    (fn [props]
      (println "RERENDERRR")
      ...]))))}
   ...])

(defn data-table [{:keys [columns data]}]
  (let [columns (clj->js columns)
        data (clj->js data)
        table (useReactTable #js {:data data
                                  :columns columns
                                  :getCoreRowModel (getCoreRowModel)})]
    [:div {:class "rounded-md border"}
     [:> Table
      [:> TableHeader
       (for [header-group (.getHeaderGroups table)]
         [:> TableRow {:key (.-id header-group)}
          (for [header (.-headers header-group)]
            [:> TableHead {:key (.-id header)
                           :colSpan (.-colSpan header)
                           :style {:width (str (.getSize header) "px")}}
             (when-not (.-isPlaceholder header)
               (flexRender (.. header -column -columnDef -header) (.getContext header)))])])]
      [:> TableBody
       (let [rows (.-rows (.getRowModel table))]
         (if (and rows (pos? (.-length rows)))
           (for [row rows]
             [:> TableRow {:key (.-id row)
                           :data-state (and (.getIsSelected row) "selected")}
              (for [cell (.getVisibleCells row)]
                [:> TableCell {:key (.-id cell)}
                 (flexRender (.. cell -column -columnDef -cell) (.getContext cell))])])
           [:> TableRow
            [:> TableCell {:colSpan (.-length columns)
                           :class "h-24 text-center"}
             "No results."]]))]]]))

(defn tasks-page []
  (let [tasks @(rf/subscribe [::subs/tasks])]
    [:div {:class "flex h-full flex-1 flex-col space-y-8 p-8"}
     ...
     [:f> data-table {:columns columns :data tasks}]]))
When tasks-page component gets re-rendered, I get multiple non-stopping "RERENDERRR" prints in my console If I change the :data parameter of data-table component to take (clj->js tasks) (and remove the data (clj->js data) from the data-table let binding) I actually fix this problem. My main question is, why?

agorgl21:03:07

It also seems that when moving the "RERENDERRR" println in the top of data-table function it still gets triggered endlessly (in case that helps)

agorgl21:03:02

It seems that according to some discussions in gh (https://github.com/TanStack/table/issues/4614) that the tanstack table wants a stable JS reference to data, which I suppose I don't provide, because in each re-render I do pass data as (clj->js data) . Is there any way to achieve this? I want to keep my data as clojurescript data structures in re-frame database and not as javascript objects

agorgl21:03:01

Seems that this can be solved using:

(defn data-table [{:keys [columns data]}]
  (let [columns (useMemo #(clj->js columns) #js [columns])
        data (useMemo #(clj->js data) #js [data])
        table (useReactTable #js {:data data
                                  :columns columns
                                  :getCoreRowModel (getCoreRowModel)})]
I'll still wait for some feedback if this is the correct solution though 🙂