Skip to content

Commit 2410690

Browse files
Merge pull request #122 from iamprich/backports-fix-for-jumping-cursor
fixes jumping cursor
2 parents f025000 + 9c925bf commit 2410690

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

ruby/hyper-component/lib/react/element.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def merge_event_prop!(event_name, &block)
127127
end
128128
end
129129

130-
def merge_built_in_event_prop!(prop_name)
130+
def merge_built_in_event_prop!(prop_name, &block)
131131
@properties.merge!(
132132
prop_name => %x{
133133
function(){
@@ -137,9 +137,17 @@ def merge_built_in_event_prop!(prop_name)
137137
if (arguments.length > 1) {
138138
all_args = Array.prototype.slice.call(arguments);
139139
other_args = all_args.slice(1, arguments.length);
140-
return #{yield(React::Event.new(`react_event`), *(`other_args`))};
140+
return #{
141+
React::State.ignore_bulk_updates(
142+
React::Event.new(`react_event`), *(`other_args`), &block
143+
)
144+
};
141145
} else {
142-
return #{yield(React::Event.new(`react_event`))};
146+
return #{
147+
React::State.ignore_bulk_updates(
148+
React::Event.new(`react_event`), &block
149+
)
150+
};
143151
}
144152
}
145153
}

ruby/hyper-component/spec/react/misc_fixes_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,23 @@ class TestComp < Hyperloop::Component
3232
end
3333
expect(page).to have_content('hello')
3434
end
35+
36+
it "does not shift cursor position during controlled input updates" do
37+
mount "TestComp" do
38+
class TestComp < Hyperloop::Component
39+
render(DIV) do
40+
INPUT(id: :input, value: state.input_value)
41+
.on(:change) { |e| mutate.input_value(e.target.value) }
42+
end
43+
end
44+
end
45+
input = find('#input')
46+
input.send_keys '1234567890'
47+
evaluate_script "$('#input').focus()[0].setSelectionRange(3, 3)"
48+
input.send_keys 'hello'
49+
expect(input.value).to eq('123hello4567890')
50+
end
51+
3552
it "and it can still use the deprecated mutate syntax" do
3653
mount "TestComp" do
3754
class TestComp < Hyperloop::Component

ruby/hyper-store/lib/react/state.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,18 @@ def bulk_update
1919
@bulk_update_flag = saved_bulk_update_flag
2020
end
2121

22+
# React already will batch together updates inside of event handlers
23+
# so we don't have to, and having Hyperstack batch them outside of the
24+
# event handler causes INPUT/TEXT/SELECT s not to work properly.
25+
# This method is called by the Component event wrapper.
26+
def ignore_bulk_updates(*args)
27+
saved_ignore_bulk_update_flag = @ignore_bulk_update_flag
28+
@ignore_bulk_update_flag = true
29+
yield(*args)
30+
ensure
31+
@ignore_bulk_update_flag = saved_ignore_bulk_update_flag
32+
end
33+
2234
def set_state2(object, name, value, updates, exclusions = nil)
2335
# set object's name state to value, tell all observers it has changed.
2436
# Observers must implement update_react_js_state
@@ -59,7 +71,7 @@ def get_state(object, name, current_observer = @current_observer)
5971
def set_state(object, name, value, delay=ALWAYS_UPDATE_STATE_AFTER_RENDER)
6072
states[object][name] = value
6173
delay = false if object.respond_to?(:set_state_synchronously?) && object.set_state_synchronously?
62-
if delay || @bulk_update_flag
74+
if !@ignore_bulk_update_flag && (delay || @bulk_update_flag)
6375
@delayed_updates ||= Hash.new { |h, k| h[k] = {} }
6476
@delayed_updates[object][name] = [value, Set.new]
6577
@delayed_updater ||= after(0.001) do
@@ -80,6 +92,8 @@ def set_state(object, name, value, delay=ALWAYS_UPDATE_STATE_AFTER_RENDER)
8092
updates.each { |observer, args| observer.update_react_js_state(*args) }
8193
end
8294
value
95+
ensure
96+
'Disabling JIT for Safari bug'
8397
end
8498

8599
def will_be_observing?(object, name, current_observer)

0 commit comments

Comments
 (0)