-
Notifications
You must be signed in to change notification settings - Fork 40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Idea: React-style state model view rendering #63
Comments
An example of a table screen def on_load
set_state({ cells: [] })
end
def set_state(state)
@cells = state[:cells]
update_table_data
end
def table_data
[{
cells: @cells
}]
end |
I like the idea of a class MyStylesheet < ApplicationStylesheet
def render
append(UIView, :wrapper) do |wrap|
wrap.append(UILabel, :first_name).data_bind("user.first_name")
wrap.append(UILabel, :last_name).data_bind("user.last_name")
end
end
end
# In screen
def on_something_tapped
set_state({ user: { first_name: "Jamon", last_name: "Holmgren" } })
end
# In the screen
def set_state(new_state)
stylesheet.set_state(new_state)
end
# Stylesheet
def set_state(new_state)
render unless @rendered
@rendered = true
data_bindings.each do |key, element|
# Extract the value from the hash path,
# e.g. "user.first_name" is new_state[:user][:first_name]
new_value = extract_value_from_hash_path(new_state, key)
# Update only if necessary
element.data(new_value) if new_value && new_value != element.data
end
end The render is only called once, but the |
Representing collections of items is another discussion, though. It's probably better to use the new |
Another idea I'm kicking around: class MyStylesheet < ApplicationStylesheet
def render
ui_view(:wrapper) do
ui_label(:first_name).data_bind("user.first_name")
ui_label(:last_name).data_bind("user.last_name")
end
end
end This is a more radical departure, though. Perhaps as an RMQ addon. |
I wrote this on the community site:
|
@willrax I think it's pretty rare that we'd have that many UI elements on an iOS screen. If so, however, I do have some ideas (see above) on how we'd accomplish the diffing/selective updates if it ended up being a performance problem. |
Another idea is to do it somewhat manually, but this would be pretty easy to implement: class MyStylesheet < ApplicationStylesheet
def render
append(UIView, :wrapper) do |wrap|
wrap.append(UILabel, :first_name)
wrap.append(UILabel, :last_name)
end
bind(:first_name, "user.first_name") # state[:user][:first_name]
bind(:last_name, "user.last_name") # state[:user][:last_name]
end
end |
Closing due to lack of interest. |
Hey @jamonholmgren, I'm still really interested in this. Seems like this could start out relatively simple. Do you have any more thoughts on this after spending more time working with React Native? |
@andrewhavens Sure! So, two things come immediately to mind. We need a standard way to implement a def render(state, root)
root.append(:container) do |v|
v.append(:other_view).data(state[:other_view_text])
v.append(:label).data(state[:label_text])
if state[:some_conditional]
v.append(:something).data(state[:something])
end
end
end One downside is that since this is imperative coding, not "describing a UI tree", it would be harder to do a diff and only update what we want to update when we call
set_state({
something: true,
items: [ "one", "two", "three" ]
}) It would do a shallow merge, like React does. Deep merge for React sounds good until you actually try to implement it and then you want to quit programming altogether. :) |
Honestly doesn't feel like it would be that difficult to do this, now that I think about it. |
Per my article posted this morning, I'd like to discuss bringing in a React-style
set_state
method onPM::Screen
and providing arender
(orlayout
) method in the RMQ stylesheet.Other things to discuss:
update_table_data
and the like, but we should discuss.Lastly, I have to thanks @twerth for building RMQ -- makes this sort of thing so easy. :-)
The text was updated successfully, but these errors were encountered: