Refs
A ref lets a component do something to an element it rendered, such as
clear a form or move the cursor into an input, like a React ref.
Create a Ref in the state and pass it as the ref attribute:
:ruby
def initialize
@form_ref = Ref.new
@input_ref = Ref.new
end
def mount
@input_ref.current.focus
end
def handle_submit(event)
event => { target: { formData: { title: } } }
Todo.add(title)
@form_ref.current.reset
@input_ref.current.focus
end
%form(ref=@form_ref onsubmit=handle_submit)
%input(ref=@input_ref name="title")
%button(type="submit") Add
ref.current is a handle for the element. Each of its methods calls
the DOM method of the same name in the browser. The calls run after the
DOM updates from the same handler, so reset sees the form as it was
just rendered. They return nil: there is no way yet to read a value
back from the browser, so read values from the event as usual.
Element methods
focus(prevent_scroll: nil, focus_visible: nil)blurclickselectresetrequest_submitscroll_into_view(behavior: nil, block: nil, inline: nil)set_selection_range(start, finish, direction = nil)show_modal,showandclose(return_value = nil), for dialogsshow_popover,hide_popoverandtoggle_popover(force = nil)
Component refs
A ref on a component points at the component instance, so a parent can call its methods:
:ruby
def initialize
@player_ref = Ref.new
end
def handle_stop
@player_ref.current.stop
end
%Player(ref=@player_ref)
When current is set
current is nil until the element or component starts, which is
after the browser has connected, and again once it is removed. During
server rendering it is always nil. A component mounts after it has
rendered, so in mount the refs of everything it rendered are set.
An element that is rendered conditionally can still be missing, so
use &. for those.
Keep the Ref in state, not ref.current. The ref follows the element
when it is rendered again, replaced by a new key, or the session moves
to another server; a stored handle would point at an element that may
be gone. A ref points at one thing at a time: render it on one element.