nx-js / observer-util

Transparent reactivity with 100% language coverage. Made with ❤️ and ES6 Proxies.
MIT License
1.2k stars 94 forks source link

Integrating NX-observe with React #6

Closed solkimicreb closed 7 years ago

solkimicreb commented 7 years ago

Hi!

Would anyone be interested in doing this. I would put it into a separate repo (like mobx and react-mobx) to keep nx-observe framework independent. If nobody is interested I will try to do it, but I am pretty much a React newbie.

SukantGujar commented 7 years ago

Added a very quick and dirty example integration of nx-observe with React.

There are few things about integrating React with libraries like mobx and now nx-observe that are conceptually against some core React principles.

The first principle is to never update props directly. A React component should not mutate its props data as its an input to the component from parent. Popular implementations like redux, reflux etc. have well defined reducers or action handlers which take care of mutation. However with an observable store, every component can directly observe only those props its interested in and has the potential to make modifications to it. In fact as the data is mutable, it should make the changes. I would recommend passing an observable Store with mutation APIs which the components can invoke, rather than directly mutating the json. I will rework the code to give an example.

The second principle is to not invoke render directly. Ideally React manages all render invocations itself. However, both Mobx and nx-observe must allow easy updates to the components observing the store. To do this, Mobx provides a higher order component called observer which internally invokes render of the wrapped component once so that it can track the references observables in it. It is effective, but I somehow find this approach not very elegant (but hey the library is very popular and fast so they must have done this with a lot of thought). I think higher order components can be one way to solve this without invoking render directly. In the code, I have attempted a simple HOC observercomponent which does just this.

solkimicreb commented 7 years ago

Hi!

Nice work! (: Thanks for all the insights about React, it really helps. I run through the code quickly but didn't try it out yet. I will check it soon and comment on the nx-observe related parts where I can. Would you be interested in taking this further into an official port?

SukantGujar commented 7 years ago

I would be glad to do that, if you could bear with my timelines. At the moment my work is at full swing, leaving time for little else.

I'd use some help myself regarding more elegant ways to work around the two problems I mentioned above :).

solkimicreb commented 7 years ago

Sure, no need to hurry. I checked the app and its great. I think mobx react uses a mixin to add observability and only wraps stateless comps with a HOC (plus adds the mixin too). About the props I am clueless, I also feel like they are awkwardly 'in the way', but I guess mobx developers felt the same way.

Some observe related stuff: Things like observer.observe(func.bind(context, arg1, arg2)) can be rewritten as observer.observe(func, context, arg1, arg2). I decided to provide this to avoid binding and closures in perf sensitive code. (This is just for the future)

I am also a bit busy now, but I will look a bit deeper into mobx-react.

solkimicreb commented 7 years ago

Hi!

@mrjjwirght started working on this too. See this repo for more. Just wanted to let you know in case you are still interested 🙂

kamicane commented 7 years ago

I have been using a very barebones Observer component that uses the same technique of initial render patch as mobx:

https://gist.github.com/kamicane/e6a434ff12e623978aba4d0d3d5fab33

I find it cleaner to subclass Component rather than monkey-patch components using decorators.

solkimicreb commented 7 years ago

Super clean!

solkimicreb commented 7 years ago

@kamicane @SukantGujar I made a react library that wraps the state into an observable and the render method into an observer (the whole thing is a single decorator). In case you are interested, it is here: https://github.com/solkimicreb/react-easy-state.

@kamicane Thanks for the gist, it was super helpful!