Class: React::State

Inherits:
Object
  • Object
show all
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

Class Method Summary collapse

Class Attribute Details

.current_observerObject (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_updateObject



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



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/react/state.rb', line 38

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

Returns:

  • (Boolean)


10
11
12
# File 'lib/react/state.rb', line 10

def has_observers?(object, name)
  !observers_by_name[object][name].empty?
end

.initialize_states(object, initial_values) ⇒ Object

initialize objects’ name/value pairs



34
35
36
# File 'lib/react/state.rb', line 34

def initialize_states(object, initial_values) # initialize objects' name/value pairs
  states[object].merge!(initial_values || {})
end

.is_observing?(object, name, current_observer) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/react/state.rb', line 89

def is_observing?(object, name, current_observer)
  current_observer && observers_by_name[object][name].include?(current_observer)
end

.removeObject

call after component is unmounted



109
110
111
112
113
114
115
116
117
# File 'lib/react/state.rb', line 109

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



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/react/state.rb', line 59

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 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
end

.set_state2(object, name, value, updates, exclusions = nil) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/react/state.rb', line 22

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



119
120
121
122
123
124
125
126
127
128
129
# File 'lib/react/state.rb', line 119

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

.statesObject



131
132
133
# File 'lib/react/state.rb', line 131

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



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/react/state.rb', line 93

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

Returns:

  • (Boolean)


85
86
87
# File 'lib/react/state.rb', line 85

def will_be_observing?(object, name, current_observer)
  current_observer && new_observers[current_observer][object].include?(name)
end