fix: avoid re-renders inside contact-list for new-chat sheet (#21640)

This change fixes some of the re-rendering issues that occur inside the contact list when creating a new chat. Most important is that we avoid extra re-renders by configuring the flat-list with stable props. And we also avoid re-rendering avatar images each time the avatar component re-renders.
This commit is contained in:
Sean Hagstrom 2024-12-04 06:30:10 -08:00 committed by GitHub
parent e0e9ab9adb
commit 62c8e73409
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 34 additions and 34 deletions

View File

@ -9,6 +9,7 @@
gestureHandlerRootHOC gestureHandlerRootHOC
FlatList FlatList
ScrollView)] ScrollView)]
[react-native.core :as rn]
[react-native.flat-list :as rn-flat-list] [react-native.flat-list :as rn-flat-list]
[reagent.core :as reagent])) [reagent.core :as reagent]))
@ -112,17 +113,21 @@
render-fn] render-fn]
:or {sticky-section-headers-enabled true} :or {sticky-section-headers-enabled true}
:as props}] :as props}]
(let [data (flatten-sections sections)] (let [data (flatten-sections sections)
render-item (rn/use-callback
(fn [p1 p2 p3 p4]
[:<>
(if (:header? p1)
[render-section-header-fn p1 p2 p3 p4]
[render-fn p1 p2 p3 p4])
(when (and render-section-footer-fn
(is-last-item-in-section data p2))
[render-section-footer-fn p1 p2 p3 p4])])
[render-fn render-section-header-fn render-section-footer-fn])]
[flat-list [flat-list
(merge props (merge props
{:data data {:data data
:render-fn (fn [p1 p2 p3 p4] :render-fn render-item
[:<> :sticky-header-indices
(if (:header? p1) (when sticky-section-headers-enabled
[render-section-header-fn p1 p2 p3 p4] (find-sticky-indices data))})]))
[render-fn p1 p2 p3 p4])
(when (and render-section-footer-fn
(is-last-item-in-section data p2))
[render-section-footer-fn p1 p2 p3 p4])])
:sticky-header-indices (when sticky-section-headers-enabled
(find-sticky-indices data))})]))

View File

@ -47,7 +47,8 @@
animating? (reagent/atom true) animating? (reagent/atom true)
set-animating-true #(reset! animating? true) set-animating-true #(reset! animating? true)
set-animating-false (fn [ms] set-animating-false (fn [ms]
(js/setTimeout #(reset! animating? false) ms))] (js/setTimeout #(reset! animating? false) ms))
on-scroll-update #(on-scroll % curr-scroll)]
(fn [{:keys [content skip-background?]}] (fn [{:keys [content skip-background?]}]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
{:keys [top] :as insets} (safe-area/get-insets) {:keys [top] :as insets} (safe-area/get-insets)
@ -94,5 +95,5 @@
:close close :close close
:scroll-enabled? scroll-enabled? :scroll-enabled? scroll-enabled?
:current-scroll curr-scroll :current-scroll curr-scroll
:on-scroll #(on-scroll % curr-scroll) :on-scroll on-scroll-update
:sheet-animating? animating?}]]]])))) :sheet-animating? animating?}]]]]))))

View File

@ -70,7 +70,7 @@
(re-frame/dispatch [:select-contact public-key]))))) (re-frame/dispatch [:select-contact public-key])))))
(defn contact-item-render (defn contact-item-render
[{:keys [public-key] :as item} set-has-error] [{:keys [public-key] :as item} _ _ {:keys [set-has-error]}]
(let [user-selected? (rf/sub [:is-contact-selected? public-key]) (let [user-selected? (rf/sub [:is-contact-selected? public-key])
on-toggle (fn [] on-toggle (fn []
(-> public-key (-> public-key
@ -86,7 +86,7 @@
item])) item]))
(defn view (defn view
[{:keys [scroll-enabled? on-scroll close]}] [{:keys [on-scroll close]}]
(let [theme (quo.theme/use-theme) (let [theme (quo.theme/use-theme)
contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter]) contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter])
selected-contacts-count (rf/sub [:selected-contacts-count]) selected-contacts-count (rf/sub [:selected-contacts-count])
@ -94,9 +94,6 @@
customization-color (rf/sub [:profile/customization-color]) customization-color (rf/sub [:profile/customization-color])
one-contact-selected? (= selected-contacts-count 1) one-contact-selected? (= selected-contacts-count 1)
[has-error? set-has-error] (rn/use-state false) [has-error? set-has-error] (rn/use-state false)
render-fn (rn/use-callback (fn [item]
(contact-item-render item set-has-error))
[set-has-error])
contacts-selected? (pos? selected-contacts-count) contacts-selected? (pos? selected-contacts-count)
{:keys [primary-name public-key]} (when one-contact-selected? {:keys [primary-name public-key]} (when one-contact-selected?
(rf/sub [:contacts/contact-by-identity (rf/sub [:contacts/contact-by-identity
@ -136,8 +133,8 @@
:render-section-header-fn contact-list/contacts-section-header :render-section-header-fn contact-list/contacts-section-header
:render-section-footer-fn contact-list/contacts-section-footer :render-section-footer-fn contact-list/contacts-section-footer
:content-container-style {:padding-bottom 70} :content-container-style {:padding-bottom 70}
:render-fn render-fn :render-fn contact-item-render
:scroll-enabled @scroll-enabled? :render-data {:set-has-error set-has-error}
:on-scroll on-scroll}]) :on-scroll on-scroll}])
(when contacts-selected? (when contacts-selected?
[rn/view [rn/view

View File

@ -7,8 +7,7 @@
[react-native.fs :as utils.fs] [react-native.fs :as utils.fs]
[react-native.platform :as platform] [react-native.platform :as platform]
[schema.core :as schema] [schema.core :as schema]
[status-im.config :as config] [status-im.config :as config]))
[utils.datetime :as datetime]))
(def ^:const image-server-uri-prefix config/STATUS_BACKEND_SERVER_IMAGE_SERVER_URI_PREFIX) (def ^:const image-server-uri-prefix config/STATUS_BACKEND_SERVER_IMAGE_SERVER_URI_PREFIX)
(def ^:const account-images-action "/accountImages") (def ^:const account-images-action "/accountImages")
@ -40,8 +39,6 @@
"/" "/"
font-file-name)))) font-file-name))))
(defn timestamp [] (datetime/timestamp))
(defn current-theme-index (defn current-theme-index
[theme] [theme]
(case theme (case theme
@ -74,7 +71,7 @@
`ring?` shows or hides ring for account with ens name" `ring?` shows or hides ring for account with ens name"
[{:keys [port public-key image-name key-uid size theme indicator-size [{:keys [port public-key image-name key-uid size theme indicator-size
indicator-border indicator-center-to-edge indicator-color ring? indicator-border indicator-center-to-edge indicator-color ring?
ring-width ratio]}] ring-width ratio clock]}]
(str (str
image-server-uri-prefix image-server-uri-prefix
port port
@ -90,7 +87,7 @@
"&theme=" "&theme="
(current-theme-index theme) (current-theme-index theme)
"&clock=" "&clock="
(timestamp) clock
"&indicatorColor=" "&indicatorColor="
(js/encodeURIComponent indicator-color) (js/encodeURIComponent indicator-color)
"&indicatorSize=" "&indicatorSize="
@ -118,7 +115,7 @@
[{:keys [port public-key key-uid theme ring? length size customization-color [{:keys [port public-key key-uid theme ring? length size customization-color
color font-size font-file uppercase-ratio indicator-size color font-size font-file uppercase-ratio indicator-size
indicator-border indicator-center-to-edge indicator-color full-name indicator-border indicator-center-to-edge indicator-color full-name
ring-width ratio]}] ring-width ratio clock]}]
(str (str
image-server-uri-prefix image-server-uri-prefix
port port
@ -144,9 +141,9 @@
"&theme=" "&theme="
(current-theme-index theme) (current-theme-index theme)
"&clock=" "&clock="
clock
"&name=" "&name="
(js/encodeURIComponent full-name) (js/encodeURIComponent full-name)
(timestamp)
"&indicatorColor=" "&indicatorColor="
(js/encodeURIComponent indicator-color) (js/encodeURIComponent indicator-color)
"&indicatorSize=" "&indicatorSize="

View File

@ -6,8 +6,7 @@
(t/deftest get-account-image-uri-test (t/deftest get-account-image-uri-test
(with-redefs (with-redefs
[sut/current-theme-index identity [sut/current-theme-index identity]
sut/timestamp (constantly "timestamp")]
(t/is (t/is
(= (=
(sut/get-account-image-uri {:port "port" (sut/get-account-image-uri {:port "port"
@ -15,6 +14,7 @@
:ratio 2 :ratio 2
:image-name "image-name" :image-name "image-name"
:key-uid "key-uid" :key-uid "key-uid"
:clock "timestamp"
:theme :dark :theme :dark
:indicator-size 2 :indicator-size 2
:indicator-color "rgba(9,16,28,0.08)" :indicator-color "rgba(9,16,28,0.08)"
@ -26,8 +26,7 @@
(t/deftest get-account-initials-uri-test (t/deftest get-account-initials-uri-test
(with-redefs (with-redefs
[sut/current-theme-index identity [sut/current-theme-index identity
colors/resolve-color str colors/resolve-color str]
sut/timestamp (constantly "timestamp")]
(t/is (t/is
(= (=
(sut/get-initials-avatar-uri (sut/get-initials-avatar-uri
@ -35,6 +34,7 @@
:public-key "public-key" :public-key "public-key"
:ratio 2 :ratio 2
:key-uid "key-uid" :key-uid "key-uid"
:clock "timestamp"
:full-name "full-name" :full-name "full-name"
:length "length" :length "length"
:size 48 :size 48
@ -49,4 +49,4 @@
:indicator-center-to-edge 6 :indicator-center-to-edge 6
:indicator-color "#0E1620" :indicator-color "#0E1620"
:ring-width 4}) :ring-width 4})
"https://localhost:port/accountInitials?publicKey=public-key&keyUid=key-uid&length=length&size=96&bgColor=%3Ablue%3Alight&color=%230E162000&fontSize=24&fontFile=%2Ffont%2FInter%20Medium.otf&uppercaseRatio=0.6&theme=:light&clock=&name=full-nametimestamp&indicatorColor=%230E1620&indicatorSize=4&indicatorBorder=0&indicatorCenterToEdge=12&addRing=1&ringWidth=8")))) "https://localhost:port/accountInitials?publicKey=public-key&keyUid=key-uid&length=length&size=96&bgColor=%3Ablue%3Alight&color=%230E162000&fontSize=24&fontFile=%2Ffont%2FInter%20Medium.otf&uppercaseRatio=0.6&theme=:light&clock=timestamp&name=full-name&indicatorColor=%230E1620&indicatorSize=4&indicatorBorder=0&indicatorCenterToEdge=12&addRing=1&ringWidth=8"))))