Class: React::State
- Inherits:
-
Object
- Object
- React::State
- Defined in:
- lib/react/state.rb
Constant Summary collapse
- ALWAYS_UPDATE_STATE_AFTER_RENDER =
if on server then we don’t wait to update the state
Hyperloop.on_client?
Class Attribute Summary collapse
-
.current_observer ⇒ Object
readonly
Returns the value of attribute current_observer.
Class Method Summary collapse
- .bulk_update ⇒ Object
- .get_state(object, name, current_observer = @current_observer) ⇒ Object
- .has_observers?(object, name) ⇒ Boolean
-
.ignore_bulk_updates(*args) ⇒ Object
React already will batch together updates inside of event handlers so we don’t have to, and having Hyperstack batch them outside of the event handler causes INPUT/TEXT/SELECT s not to work properly.
-
.initialize_states(object, initial_values) ⇒ Object
initialize objects’ name/value pairs.
- .is_observing?(object, name, current_observer) ⇒ Boolean
-
.remove ⇒ Object
call after component is unmounted.
-
.set_state(object, name, value, delay = ALWAYS_UPDATE_STATE_AFTER_RENDER) ⇒ Object
ReactDOM.unstable_batchedUpdates does not seem to improve things here, ill leave it here commented for reference and later investigation if ‘ReactDOM.unstable_batchedUpdates !== undefined` %x{ ReactDOM.unstable_batchedUpdates(function(){ #{ |observer, args| observer.update_react_js_state(*args) } }); } else # run the other one.
- .set_state2(object, name, value, updates, exclusions = nil) ⇒ Object
-
.set_state_context_to(observer, rendering = nil) ⇒ Object
wrap all execution that may set or get states in a block so we know which observer is executing.
- .states ⇒ Object
-
.update_states_to_observe(current_observer = @current_observer) ⇒ Object
should be called after the last after_render callback, currently called after components render method.
- .will_be_observing?(object, name, current_observer) ⇒ Boolean
Class Attribute Details
.current_observer ⇒ Object (readonly)
Returns the value of attribute current_observer.
8 9 10 |
# File 'lib/react/state.rb', line 8 def current_observer @current_observer end |
Class Method Details
.bulk_update ⇒ Object
14 15 16 17 18 19 20 |
# File 'lib/react/state.rb', line 14 def bulk_update saved_bulk_update_flag = @bulk_update_flag @bulk_update_flag = true yield ensure @bulk_update_flag = saved_bulk_update_flag end |
.get_state(object, name, current_observer = @current_observer) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/react/state.rb', line 50 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 |
.has_observers?(object, name) ⇒ Boolean
10 11 12 |
# File 'lib/react/state.rb', line 10 def has_observers?(object, name) !observers_by_name[object][name].empty? end |
.ignore_bulk_updates(*args) ⇒ Object
React already will batch together updates inside of event handlers so we don’t have to, and having Hyperstack batch them outside of the event handler causes INPUT/TEXT/SELECT s not to work properly. This method is called by the Component event wrapper.
26 27 28 29 30 31 32 |
# File 'lib/react/state.rb', line 26 def ignore_bulk_updates(*args) saved_ignore_bulk_update_flag = @ignore_bulk_update_flag @ignore_bulk_update_flag = true yield(*args) ensure @ignore_bulk_update_flag = saved_ignore_bulk_update_flag end |
.initialize_states(object, initial_values) ⇒ Object
initialize objects’ name/value pairs
46 47 48 |
# File 'lib/react/state.rb', line 46 def initialize_states(object, initial_values) # initialize objects' name/value pairs states[object].merge!(initial_values || {}) end |
.is_observing?(object, name, current_observer) ⇒ Boolean
103 104 105 |
# File 'lib/react/state.rb', line 103 def is_observing?(object, name, current_observer) current_observer && observers_by_name[object][name].include?(current_observer) end |
.remove ⇒ Object
call after component is unmounted
123 124 125 126 127 128 129 130 131 |
# File 'lib/react/state.rb', line 123 def remove # call after component is unmounted raise "remove called outside of watch block" unless @current_observer current_observers[@current_observer].each do |object, names| names.each do |name| observers_by_name[object][name].delete(@current_observer) end end current_observers.delete(@current_observer) end |
.set_state(object, name, value, delay = ALWAYS_UPDATE_STATE_AFTER_RENDER) ⇒ Object
ReactDOM.unstable_batchedUpdates does not seem to improve things here, ill leave it here commented for reference and later investigation if ‘ReactDOM.unstable_batchedUpdates !== undefined`
%x{
ReactDOM.unstable_batchedUpdates(function(){
#{updates.each { |observer, args| observer.update_react_js_state(*args) }}
});
}
else # run the other one
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/react/state.rb', line 71 def set_state(object, name, value, delay=ALWAYS_UPDATE_STATE_AFTER_RENDER) states[object][name] = value delay = false if object.respond_to?(:set_state_synchronously?) && object.set_state_synchronously? if !@ignore_bulk_update_flag && (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 elsif @rendering_level == 0 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 ensure 'Disabling JIT for Safari bug' end |
.set_state2(object, name, value, updates, exclusions = nil) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/react/state.rb', line 34 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 |
.set_state_context_to(observer, rendering = nil) ⇒ Object
wrap all execution that may set or get states in a block so we know which observer is executing
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/react/state.rb', line 133 def set_state_context_to(observer, rendering = nil) # wrap all execution that may set or get states in a block so we know which observer is executing saved_current_observer = @current_observer @current_observer = observer @rendering_level += 1 if rendering return_value = yield return_value ensure @current_observer = saved_current_observer @rendering_level -= 1 if rendering return_value end |
.states ⇒ Object
145 146 147 |
# File 'lib/react/state.rb', line 145 def states @states ||= Hash.new { |h, k| h[k] = {} } end |
.update_states_to_observe(current_observer = @current_observer) ⇒ Object
should be called after the last after_render callback, currently called after components render method
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/react/state.rb', line 107 def update_states_to_observe(current_observer = @current_observer) # should be called after the last after_render callback, currently called after components render method raise "update_states_to_observer called outside of watch block" unless current_observer current_observers[current_observer].each do |object, names| names.each do |name| observers_by_name[object][name].delete(current_observer) end end observers = current_observers[current_observer] = new_observers[current_observer] new_observers.delete(current_observer) observers.each do |object, names| names.each do |name| observers_by_name[object][name] << current_observer end end end |
.will_be_observing?(object, name, current_observer) ⇒ Boolean
99 100 101 |
# File 'lib/react/state.rb', line 99 def will_be_observing?(object, name, current_observer) current_observer && new_observers[current_observer][object].include?(name) end |