helix

JonR 2021-10-15T21:57:23.184800Z

Just did a long trip down the rabbit hole to really try and understand this and thought I would share thoughts. Main take aways were: • Having used reagent for the last 6+ years led to a major misconception that React defaulted to compare props, now I understand that Reagent does this by default not react • Even if you are passing immutable data structures as props you are still creating a new props map • Deep equals (`=`) will work in this case because values can be equal but identical? will fail • The function @lilactown shared works because it checks shallow equality via map entry count and identical? @lilactown you called all this out but I still needed to bang my head against the wall a bit and work with a team member to make an exhaustive test. One more question, since we are using our own defnc with a factory component flag we need this custom memo fn right? Meaning, if we were using raw dom tags with prop maps those would work as expected with the default memo comparator?

👍🏻 1
lilactown 2021-10-15T23:46:11.187200Z

@jon693 I had to bang my head on it a lot until it sunk in 🙂 glad I was able to help a bit. > since we are using our own `defnc` with a factory component flag we need this custom memo fn right? that's right. if you were using defnc without the :define-factory feature flag turned on, which means you would create elements out of your components using ($ my-component ,,,) instead of (my-component ,,,), then you would not need the custom factory-props-kvs-identical? compare I wrote above

JonR 2021-10-15T23:48:21.190300Z

If I remember right we needed the factory bit so we could call our components without $.

JonR 2021-10-15T23:48:45.191Z

So maybe that added extra complexity

JonR 2021-10-15T23:48:55.191300Z

Err, it did!

lilactown 2021-10-15T23:50:22.192500Z

yup. the reason why memo is misbehaving here is that ($ my-component {:foo "bar" :baz 123}) turns the map you pass in to a JS object, {"foo": "bar", "baz": 123} , that React can read and compare with memo. the factory function doesn't turn the map you pass in, into a JS object. instead, it passes it as a single prop, {"helix/props": {:foo "bar", :baz 123}} React's memo by default compares each key in the props object using identical? . so it will compare the map in the "helix/props" property between each render, get a different result, and fail the memo check. using $ the memo check would succeed and it wouldn't bother calling the component.

lilactown 2021-10-15T23:50:50.193200Z

the factory-props-kvs-identical? function essentially replicates this logic that React does with the props object, with the nested "helix/props" map

lilactown 2021-10-15T23:51:33.194200Z

I think this should be the default behavior of helix.core/memo tbh I just hadn't run into this edge case before. I don't use :define-factory

JonR 2021-10-15T23:52:24.194700Z

Doh, which is why helix props are always referential different

JonR 2021-10-15T23:53:04.195Z

In our defnc case

lilactown 2021-10-15T23:53:24.195200Z

yep exactly! 😄