Improve JS value detection
When calling adapt-react-class props of type JS array are not recognized as JS value: js-val? should also consider array type.
This forces Clojure data serialization via clj->js that might not be wanted in some cases.
Can you provide some example cases? Is array as props even valid in React?
IIRC, Clojure data serialization will always happen with adapt-react-class, but in that case user shouldn't use that function anyway, but use r/create-element to pass the Clojure data into component.
ReactNative's FlatList component's data prop requires an array. I found a workaround here https://github.com/status-im/status-react/blob/d05f50db6238117f1cee7bdff8973ac1b7802d14/src/status_im/ui/components/list/views.cljs#L110 , but it would be nice to not have to do this.
Right this is indeed my use case.
Looking at this, I don't understand what is the problem.
js-val? checks if the value is something that is already js-value, and if it is, like number of string (or array), it is not converted from Clojure to JS.
reagent.impl.template.js_val_QMARK_([1, 2]);
true
reagent.impl.template.js_val_QMARK_({a: 1});
false
reagent.impl.template.js_val_QMARK_("1");
true
I tested this with a component taking props map containing property with array value, and single child value which is array. The values are correctly passed into the React component as is.
(def c (create-react-class ...))
(def x (adapt-react-class c))
(r/render [x {:data #js [1 2 3]} #js [4 5]])
Not sure if I'm seeing the same problem but I'm having a similar issue with a flat list where each item is taking an admittedly crazy huge props map (megabytes of data if printed). For some reason I can't quite pinpoint reagent deems it necessary to convert this insane props map resulting in the render taking seconds.
This is extra delicate since flat-list is often used to render thousands of items making it really important for components to be able to quickly say "don't re-render me!"
Here's an example of how I use flat-list
[rn/flat-list
{:key-extractor (fn [item _index] (str (get-in item [:title-metadata :id])))
:renderItem (fn [js-kwargs] (reagent/as-element [continue-reading-list-item (aget js-kwargs "item")])) ; Item is crazy huge.
:data (apply array
(for [title titles]
{:title-metadata title
:on-press on-press
:bookmarked-props (core/create-bookmarked-props state module-context {:item-data title})
:adjusted-client-time (response/adjust-client-time response (time/now))}))}]