Last active
June 21, 2022 13:02
-
-
Save geraldodev/144ac42fca696431991f46b42c6f5149 to your computer and use it in GitHub Desktop.
https://github.com/TanStack/virtual rowVirtualizer helix snippet
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns crudis.ui.root | |
(:require | |
["@tanstack/react-virtual" :refer [useVirtualizer]] | |
["react" :as React] | |
[goog.object :as gobj] | |
[helix.core :as hx :refer [defnc $ <> fnc]] | |
[helix.dom :as d :refer [div a button]] | |
[helix.hooks :as hooks :refer [use-state]] | |
[paqueta.fetch :as fetch] ;; lambdaisland fetch | |
)) | |
(defnc EmployeesView | |
[] | |
(let [[employees set-employees] (hooks/use-state nil) | |
get-item #(aget employees %) ;; employess is a js vec | |
;; this is the key. you need to pass a ref to store the current position of the row virtualizer | |
employee-list-ref (React/useRef) | |
^js rowVirtualizer (useVirtualizer #js {:count (count employees) ;; count based on the current fetched employees | |
;; a function to return the current position | |
:getScrollElement #(gobj/get employee-list-ref "current") | |
;; the estimate size of the item. It could be dynamic, but in this case it's fixed, in px | |
:estimateSize (constantly 30) | |
;; the number of rows that'll be computed by the virtualizer beyond what is being watched | |
;; in order to avoid momentary blank items | |
:overscan 3 | |
;; you can provide a item key factory. that would be usefull if you want keys | |
;; with meaningfull data | |
;; i've put the console.log here to understand when this function is called | |
;; when you provide it. its called for all items of the index (based on the count) | |
;; note that calling this function just computes the key, it does not render | |
;; the items | |
; :getItemKey (fn [index] | |
; ; (js/console.log "getItemKey" | |
; ; (count employees) | |
; ; index) | |
; (gobj/get (get-item index) | |
; "employee_id")) | |
})] | |
(hooks/use-effect | |
:once | |
(p/let [resp (fetch/get "/api/employees" | |
{:accept :json | |
:content-type :json})] | |
(when (= (:status resp) 200) | |
(let [b (:body resp)] | |
(when (not= b employees) | |
(set-employees b)))))) | |
(div | |
{:class "px-2"} | |
"EmployeesView" | |
(div | |
{:class "space-x-4"} | |
;; here is the div that will be "row virtualized" | |
;; with this library you have to provide your own style which I think it's awesome. | |
;; look the super important ref as a parent of the inner div | |
;; overflow auto is to enable scrolling | |
(div | |
{:ref employee-list-ref | |
:style {:height "100px" | |
:width "300px" | |
:overflow "auto"}} | |
;; an inner div whose the height is the totalSize of the virtualizer | |
;; the position needs to be relative to anchor the items. the items needs to be position absolute | |
(div {:style {:height (str (.getTotalSize rowVirtualizer) "px") | |
:width "100%" | |
:position "relative"}} | |
; (js/console.log (count (.getVirtualItems rowVirtualizer))) | |
;; virtual items | |
(for [vi (.getVirtualItems rowVirtualizer)] | |
;; lookup the employee by index of the virtual item | |
(let [employee (get-item (.-index vi))] | |
; (js/console.log employee) | |
(div | |
{:key (.-index vi) ;; key to keep react happy | |
;; these items will be anchored on the position: relative parent | |
:style {:position "absolute" | |
:top 0 | |
:left 0 | |
:width "100%" | |
:height (str (.-size vi) "px") | |
:transform (str "translateY(" (.-start vi) "px)")}} ;; css trickery to position absolute Y axis | |
(str "idx " (.-index vi) | |
" key " (.-key vi) " " | |
(gobj/get employee "first_name"))))))))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment