Skip to content
This repository was archived by the owner on Oct 19, 2018. It is now read-only.

React::State fixes and new functions #178

Closed
catmando opened this issue Oct 25, 2016 · 4 comments
Closed

React::State fixes and new functions #178

catmando opened this issue Oct 25, 2016 · 4 comments

Comments

@catmando
Copy link
Contributor

Hypermesh (synchromesh, whatever) needs the following patches to React::State which should be all backwards compatible:

module  React
  # add has_observers? and bulk_update methods, and patch set_state so that
  # delayed updates are grouped together and sent at once to update_react_js_state
  # see the component_patches.rb file for how that works

  # also fix an issue so that if state changes before it is accessed, this will not cause a delayed rendering of the component that accessed it.
  class State
    class << self
      def has_observers?(object, name)
        !observers_by_name[object][name].empty?
      end

      def set_state2(object, name, value, updates, exclusions = nil)
        # set object's name state to value, tell all observers it has changed.
        # Observers must implement update_react_js_state
        object_needs_notification = object.respond_to? :update_react_js_state
        observers_by_name[object][name].dup.each do |observer|
          next if exclusions && exclusions.include?(observer)
          updates[observer] += [object, name, value]
          object_needs_notification = false if object == observer
        end
        updates[object] += [nil, name, value] if object_needs_notification
      end

      def bulk_update
        saved_bulk_update_flag = @bulk_update_flag
        @bulk_update_flag = true
        yield
      ensure
        @bulk_update_flag = saved_bulk_update_flag
      end

      def get_state(object, name, current_observer = @current_observer)
        # get current value of name for object, remember that the current object depends on this state,
        # current observer can be overriden with last param
        if current_observer && !new_observers[current_observer][object].include?(name)
          new_observers[current_observer][object] << name
        end
        if @delayed_updates && @delayed_updates[object][name]
          @delayed_updates[object][name][1] << current_observer
        end
        states[object][name]
      end

      def set_state(object, name, value, delay=nil)
        states[object][name] = value
        if delay || @bulk_update_flag
          @delayed_updates ||= Hash.new { |h, k| h[k] = {} }
          @delayed_updates[object][name] = [value, Set.new]
          @delayed_updater ||= after(0.001) do
            delayed_updates = @delayed_updates
            @delayed_updates = Hash.new { |h, k| h[k] = {} } # could this be nil???
            @delayed_updater = nil
            updates = Hash.new { |hash, key| hash[key] = Array.new }
            delayed_updates.each do |object, name_hash|
              name_hash.each do |name, value_and_set|
                set_state2(object, name, value_and_set[0], updates, value_and_set[1])
              end
            end
            updates.each { |observer, args| observer.update_react_js_state(*args) }
          end
        else
          updates = Hash.new { |hash, key| hash[key] = Array.new }
          set_state2(object, name, value, updates)
          updates.each { |observer, args| observer.update_react_js_state(*args) }
        end
        value
      end
    end
  end
end
@zetachang
Copy link
Member

also fix an issue so that if state changes before it is accessed, this will not cause a delayed rendering of the component that accessed it.

Would you mind providing an example for this case?

@zetachang
Copy link
Member

Also this patch make this test case https://github.com/ruby-hyperloop/reactrb/blob/master/spec/react/state_spec.rb#L26 failed. It try to call setState during render methods.

zetachang added a commit that referenced this issue Oct 26, 2016
@catmando
Copy link
Contributor Author

okay I reproduced this... glad the test caught it...

@catmando
Copy link
Contributor Author

okay that patch was missing the critical line that associated with that failing spec.

all tests now passing, and hyper-mesh is also passing.

Lets get this baby released!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants