helix

https://github.com/Lokeh/helix
2020-05-31T14:40:50.053200Z

@lilactown Do you advise some integration with css-in-js like $ ? Material-ui for example, it bundles a js-in-css solution https://gist.github.com/geraldodev/a9b60dd611d1628f9413dd6de6c3c974#file-material_ui_helix-cljs-L14 . It avoids global css which is a good thing.

wilkerlucio 2020-05-31T19:33:58.053600Z

I'm playing with Helix and React Native, I'm trying to understand the error here:

(apply $ rn/View {:style #js {:flex 1 :alignItems "center" :justifyContent "center"}}
      [(rnc/text {:style #js {:fontSize 36}} "Hello Helix!")
       (rnc/button {:title "Click me"})])

wilkerlucio 2020-05-31T19:34:20.054100Z

the code is for experimenting purposes (trying to wrap react native stuff with factory)

wilkerlucio 2020-05-31T19:34:43.054600Z

but that code doesn't work, it errors with [object Object] is not ISeqable

wilkerlucio 2020-05-31T19:35:13.055300Z

the stack from RN is quite incomplete, so not sure, I was using the apply $ to isolate the constructor

wilkerlucio 2020-05-31T19:35:25.055700Z

when I use createElement directly from React it works fine

wilkerlucio 2020-05-31T19:37:31.056100Z

digging a bit, the problem is happening during -native-props call

alidlorenzo 2020-05-31T20:46:22.057400Z

doing this (apply helix.core/$ rn/Text {:style #js {:flex 1}} ["Hello" "World"]) works for me so I imagine the error has to do with the component children

wilkerlucio 2020-05-31T21:22:11.058600Z

@alidcastano I ran a couple of experiments to test that, but in the end, when I kept the props clean, it failed, when used the :style, it broke

wilkerlucio 2020-05-31T21:22:51.059300Z

was specifically problem with rn/View from React Native from MacOS, and I can see a difference, the View is a string component (native component), the others are not

wilkerlucio 2020-05-31T21:23:06.059700Z

so I'm guessing the issue is with the fn version of $ when used with native elements

wilkerlucio 2020-05-31T21:24:28.060Z

you can break any with: (apply $ "div" {:style #js {:flex 1}} ["child"])

wilkerlucio 2020-05-31T21:37:48.061200Z

actually, I'm writing an issue, but as I test more (not on RN now, just on regular react on browser) I see it breaks with this: ($ "div" {:style #js {:flex 1}})

alidlorenzo 2020-05-31T22:06:21.062700Z

you might want to pass ^:native to $ that might fix it

wilkerlucio 2020-05-31T22:06:27.063Z

@alidcastano I figured a different problem, not really an issue per se, but a confusing situation

alidlorenzo 2020-05-31T22:06:27.063100Z

but this looks to still be a bug

wilkerlucio 2020-05-31T22:06:31.063300Z

I described that in: https://github.com/Lokeh/helix/issues/61

šŸ‘ 1
lilactown 2020-05-31T23:10:39.064400Z

@wilkerlucio is there a particular reason youā€™re passing in styles as a JS object instead of a map?

wilkerlucio 2020-05-31T23:11:04.065Z

the trick part is because its not clear with RN components are native and which are not

wilkerlucio 2020-05-31T23:11:34.066100Z

and that may vary depending on which RN impl its being targetted (mac os RN may have different settings than Windows, than ios, etc... and those can change over time)

lilactown 2020-05-31T23:11:46.066600Z

the idea is that if youā€™re using $ then you should be able to just passing in maps

lilactown 2020-05-31T23:12:03.067400Z

so Iā€™m not sure yet why youā€™d want to literally pass in a JS obj yet

wilkerlucio 2020-05-31T23:12:12.067700Z

for example, Button in RN for MacOS is not a native component

lilactown 2020-05-31T23:12:29.068200Z

what do you mean by ā€œnativeā€ exactly?

wilkerlucio 2020-05-31T23:12:46.068500Z

the same thing you mean in helix when you check for native when running $

wilkerlucio 2020-05-31T23:12:56.068900Z

if its a string or keyword

wilkerlucio 2020-05-31T23:13:05.069300Z

or if its a component

lilactown 2020-05-31T23:13:09.069500Z

okay, itā€™s a bit of a leaky thing beyond react-dom so thatā€™s why iā€™m asking

lilactown 2020-05-31T23:13:11.069700Z

gotcha

wilkerlucio 2020-05-31T23:14:15.071100Z

yeah, so using the js-obj could be the safe version for incosistent situations like this

lilactown 2020-05-31T23:14:45.071900Z

yeah thereā€™s a couple ways to handle this, at the application level and at the library (helix level)

lilactown 2020-05-31T23:15:23.072700Z

one thing you can do is annotate the Button symbol with ^:native

lilactown 2020-05-31T23:15:34.073100Z

e.g. ($ ^:native rn/Button {:style {:flex 1}})

wilkerlucio 2020-05-31T23:16:16.073500Z

but then I have to know which component is which (native or not)

wilkerlucio 2020-05-31T23:16:29.073900Z

if I could just throw #js in all of then, I can avoid caring about it

wilkerlucio 2020-05-31T23:16:53.074600Z

also, I fear changes between versions, a non-native component today may be turned native on the next version

lilactown 2020-05-31T23:17:31.075500Z

the ā€œnativeā€ classification is not really useful beyond react-dom

lilactown 2020-05-31T23:17:52.076100Z

I regret adding it tbh

lilactown 2020-05-31T23:18:09.076900Z

the only thing that really matters is whether a component expects :style as a JS object or not

lilactown 2020-05-31T23:18:26.077300Z

so all react-native components are ā€œnativeā€ in that sense

wilkerlucio 2020-05-31T23:18:41.077600Z

yeah, but in impl that varies, which is the issue (which is not true for react dom)

lilactown 2020-05-31T23:19:11.078400Z

when you use the $ macro it doesnā€™t really tho

lilactown 2020-05-31T23:19:29.078900Z

($ foo) is always assumed to be non-ā€œnativeā€

lilactown 2020-05-31T23:19:36.079200Z

because itā€™s a symbol

wilkerlucio 2020-05-31T23:19:45.079600Z

yeah, I only have problems when using props with :style

wilkerlucio 2020-05-31T23:19:59.079800Z

ah, sorry, gotcha

wilkerlucio 2020-05-31T23:20:14.080300Z

yeah, I got the problem because I'm wrapping the components with factory

lilactown 2020-05-31T23:20:40.080900Z

it sounds like e.g. rn/View is actually a string?

wilkerlucio 2020-05-31T23:20:46.081200Z

yup

lilactown 2020-05-31T23:20:48.081300Z

šŸ˜µ

wilkerlucio 2020-05-31T23:20:53.081600Z

that's what I mean by native šŸ˜›

lilactown 2020-05-31T23:20:54.081800Z

I never expected that

wilkerlucio 2020-05-31T23:22:05.082Z

rn/View
=> "RCTView"
rn/Text
=>
#js{"$$typeof" "Symbol(react.forward_ref)",
    :render #object[Text],
    :displayName "Text",
    :propTypes #js{:ellipsizeMode #object[bound checkType],
                   :numberOfLines #object[bound checkType],
                   :textBreakStrategy #object[bound checkType],
                   :onLayout #object[bound checkType],
                   :onPress #object[bound checkType],
                   :onLongPress #object[bound checkType],
                   :pressRetentionOffset #object[bound checkType],
                   :selectable #object[bound checkType],
                   :selectionColor #object[bound colorPropType],
                   :suppressHighlighting #object[bound checkType],
                   :style #object[Function],
                   :testID #object[bound checkType],
                   :nativeID #object[bound checkType],
                   :allowFontScaling #object[bound checkType],
                   :maxFontSizeMultiplier #object[bound checkType],
                   :accessible #object[bound checkType],
                   :adjustsFontSizeToFit #object[bound checkType],
                   :minimumFontScale #object[bound checkType],
                   :disabled #object[bound checkType],
                   :dataDetectorType #object[bound checkType]}}
rn/Button
=> #object[Button]

lilactown 2020-05-31T23:22:27.082300Z

wild

lilactown 2020-05-31T23:22:36.082600Z

okay

lilactown 2020-05-31T23:25:27.083600Z

I donā€™t really exercise the runtime version of $ much

wilkerlucio 2020-05-31T23:28:12.084700Z

no worries, I'm just a new user hitting unexplored code paths šŸ™‚

lilactown 2020-05-31T23:29:22.085600Z

FWIW what Iā€™d like to do is create a namespace of macros similar to helix.dom

wilkerlucio 2020-05-31T23:38:50.086100Z

@lilactown and you plan to also support #js style on native?

wilkerlucio 2020-05-31T23:39:08.086600Z

I think the macro ns may be a problem, because you can't know what to expect from the components

wilkerlucio 2020-05-31T23:39:28.087100Z

even though Button is not native on MacOS RN, it may be native in other impls

wilkerlucio 2020-05-31T23:39:42.087500Z

so we can't know for sure what each is, makes sense?

lilactown 2020-05-31T23:42:56.089100Z

@wilkerlucio using a macro routes around this problem completely

lilactown 2020-05-31T23:43:09.089500Z

the macro $ is completely consistent

lilactown 2020-05-31T23:43:51.090700Z

($ ^:native rn/View {:style {flex 1}}) will always convert the :style prop to a JS object

lilactown 2020-05-31T23:44:23.091600Z

$ checks at macro time whether the first argument is a string/keyword or a symbol

lilactown 2020-05-31T23:44:44.092300Z

if itā€™s a symbol, it treats it as ā€œnon-nativeā€ unless itā€™s annotated with ^:native metadata

lilactown 2020-05-31T23:45:07.093Z

so rn/View can go from at runtime being a string, function, class, memoized, whatever, it doesnā€™t matter

lilactown 2020-05-31T23:46:14.094700Z

a macro would do something like: (defmacro view [& args] `($ ^:native rn/View ~@args)) which would always be unambiguous. no matter what rn/View is at runtime, it would always have the same behavior

lilactown 2020-05-31T23:49:11.097800Z

letā€™s define native to be: ā€œa component which requires transformation of props before construction, e.g. :style prop to be a JS object, :class to be renamed to :className, etc.ā€

lilactown 2020-05-31T23:50:01.099Z

then whether or not rn/View is a string or not is irrelevant, it will always be ā€œnativeā€. the detection of string/keyword is just a dumb heuristic to try and get that information at compile time

lilactown 2020-05-31T23:51:00.100400Z

the inconsistency weā€™re running into now is that if you apply this same heuristic at runtime, itā€™s even dumber, because apparently React Native has some of itā€™s ā€œnativeā€ components as strings and other ā€œnativeā€ components as functions / memoized components /etc.

lilactown 2020-05-31T23:51:27.100800Z

so the easy answer is: donā€™t do this at runtime :P

lilactown 2020-05-31T23:51:40.101300Z

but Iā€™ll have to think more about this issue before coming up with an encompassing solution

lilactown 2020-05-31T23:51:51.101700Z

I wonā€™t be at a computer today, so fix will have to wait until later this week

lilactown 2020-05-31T23:52:05.102300Z

for now, I can probably put a bandaid on it by not blowing up if you pass in a JS object

lilactown 2020-05-31T23:52:25.102900Z

but ultimately I need to think harder on the API of $ and how it extends beyond react-dom