ruby-hyperloop / hyper-react

The project has moved to Hyperstack!!
https://hyperstack.org/
MIT License
285 stars 14 forks source link

deprecate Observables #163

Open catmando opened 8 years ago

catmando commented 8 years ago

Observables should be deprecated. This was largely a ruby-ized version of the old react.js links. There are better patterns now (i.e. events or stores)

(@zetachang - there is a deprecation method available... also under the hood the observable class is still used I believe, so this just a matter of pulling any special handling in the param method.)

zetachang commented 7 years ago

Actually I am not quite familiar with the Observable code base, so here is a first scan of discovery.

So we are going to deprecate the following APIs,

  1. param :foo, type: React::Observable
  2. state.foo! when used without any argument. (state.foo! new_foo should work as before)
catmando commented 7 years ago

Hmmm...

Okay well point 2 is definitely NO

being able to say state.foo! without params is vital because it allows you to do this:

state.foo! << 'new item'

The value returned by state.foo! (without params) is indeed an observable object, that will update the state whenever it sees action applied to that object. Its basically an alternative to immutable objects. Instead of forcing everything to be immutable, it allows mutations on state values that can be recorded and notify react.

param :foo, type: React::Observable is a special case that allows the observable to be passed along to a component, and then within that component you can say

Now that I am thinking about it there is little point in removing the special observable params handling, it may not be used often, but it costs almost nothing, so why not leave it?

catmando commented 7 years ago

suggest we just close...

zetachang commented 7 years ago

Now I got the point. And I think this is related to https://github.com/reactrb/reactrb/issues/136, right?

So instead of deprecating this, maybe we could extract this as a separate module first,

  1. Basic StateWrapper will only allow method like state.attr & state.attr = new_value
  2. All interpretation of state.attr! will be extracted as something like ObservableHelpers and could be included by default.

Also some discovery to share, there is some similar JS libs like Baobab or react-cursor which I found similar to the approach we are using.

catmando commented 7 years ago

Yes.. frankly I think reactrb is way ahead on this... its simple easy and elegant.

If we wanted to we could take one step further I think:

We could build new versions of all the opal standard libraries where any mutations call react set state.

class Array
  attr_accessor :observer
  alias_method "old_push", "push"
  def push(*args)
    old_push.tap { |x| observer.call(x) if observer }
  end
end

my_array = [1, 2, 3]
puts my_array
my_array.observer = lambda { |*args| puts "observed #{args}"}
my_array.push 4
puts my_array

Now we would simply on assignment of any object to a state object start observing the object for mutations.

In addition we could provide some method that lets you declare which methods of a class are mutators, so you can build new classes.

Its a lot of work to get rid of remembering to do the "!" when updating a state, but it would be fun.