Support declarative API in React with lazyGet and set methods #3869
DonnyVerduijn
started this conversation in
Ideas
Replies: 1 comment 2 replies
-
@urugator Can we get any traction with this? Would be great to have some correspondence. |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Currently, we expose a
useLocalObservable
hook frommobx-react-lite
, but after using it shortly, i realized that it was far from ideal, having to call any defined methods inside the hook, from either arrow functions passed to props or using React.useCallback, to preventthis
being bound to the call site. To solve this problem, i decided to autobind methods in a custom hook i calleduseMobx
.That solved some of the problems, but luckily not all. I soon realized that i wanted to use late dereferencing as much as possible and took some inspiration from the docs, by doing prop drilling "render prop" style, by providing a reference to defined functions in the hook, as props to child components. However, it still required me to define separate functions for every property in this fashion.
So, then it came to my mind that we could get rid of these methods provided to
useLocalObservable
and attach memoizedset
andlazyGet
methods to the observable returned from the hook, which would provide stable references across re-renders, yet provide the functions to the leaf component to do late dereferencing. And so i was able to create something, from which i believe it deserves a place inmobx-react-lite
.Note that in the optional map function that we provide as the second argument to
lazyGet
andset
, the type of the parameter is correctly inferred by the associated prop type or property key. If omitted, the identity function is applied here. The property key provided as the first argument, is itself typed as a union of all possible dot-separated paths, which matches the implementation that parses and traverses the path to get the observable value.In this specific example,
OnOffSwitch
(or any other component), is assumed to have agetValue
prop and is wrapped byobserver
, calling the function that gets provided to itsgetValue
prop.The exact implementation of the hook could vary, given the dependency on
remeda
andhotscript
in the example below. Memoized calls tolazyGet
andset
effectively eliminate the need forReact.useCallback
in components, as we rely on the stable reference returned from the hook.For reference, here is a memoize implementation to complement the example. Note that it stringifies all of the arguments, so it is not very efficient or safe in all circumstances.
Please give it a try and let me know what you think. If it is not feasible to include it in
mobx-react-lite
, i would love to have a discussion about the potential problems at scale with this approach. I believe that ideally, we should track if observables stay unobserved after component unmounts, to do some garbage collection along the way. Shamelessly tagging @mweststrate here.EDIT: After giving it some more thought, i think one of the important considerations is how to deal with arrays. I would say that indexed lookup is out of question and arrays should be considered atomic units. The rationale behind this would be, that we don't want memoized functions for indexes that might be removed. Now the problem that appears, is how we gain access to the same lazyGet and set methods after iterating over an array. Given we deal with observable objects again that aren't extended, the question comes up if we rather need to extend any prototypes with these set and lazyGet methods?
Another question is how we want to support changing multiple properties at once. Personally i don't feel we should recommend this api just for single property lookups/writes if it can't support multiple, so that is also something to think about.
Beta Was this translation helpful? Give feedback.
All reactions