I am hoping that someone can point me to the best way to handle loading state in a top level Reactrb component with is lazy loading data through Reactive Record.
My gaol is for the top level component to display a wait state while its children components get the data they need to render and then render the whole component quickly. I don't want individual wait states with child components as this creates a 'jerky' experience when there is a lot of data to load.
If you consider this example:
class PostsWithCommentsList < React::Component::Base
before_mount do
state.posts! Post.all
end
def everything_loaded?
#how do I know when all posts and all comments are loaded?
end
def render
div do
ul do
state.posts.each do |post|
li { post.title }
ul do
post.comments.each do |comment|
li { comment.body }
end
end
end
end if everything_loaded?
end
end
end
How do I get the everything_loaded? method to check that all th Posts and all the Comments have been loaded so the component draws quickly and smoothly?
All help very welcome. Thank you
There is a feature of ReactiveRecord that isn't finished, but is at a point where it can be useful. It's called WhileLoading, and the goal was to be able to say something like:
def render
div do
ul do
state.posts.each do |post|
li { post.title }
ul do
post.comments.each do |comment|
li { comment.body }
end
end
end
end.while_loading do
# Some kind of loading screen
end
end
end
Basically you would call that method on the end of the element you want to have have something shown while it is loading, and then pass in what you want shown. Under the hood this would just show/hide the element instead of not rendering.
Unfortunately, this isn't fully working yet, but here's how it can be used.
after_mount do
@initial_data_loaded = false
Element['.content-loading'].hide
Element['.loading-div'].show
end
def toggle_loading
return if @initial_data_loaded
if ReactiveRecord::WhileLoading.quiet?
Element['.content-loading'].show
Element['.loading-div'].hide
@initial_data_loaded = true
end
end
def render
div do
div.content_loading do
ul do
state.posts.each do |post|
li { post.title }
ul do
post.comments.each do |comment|
li { comment.body }
end
end
end
end
end
div.loading_div(style: { display: 'none' }) do
# Your loading screen
end
end.tap { toggle_loading }
end
It's a little dirty, but that should accomplish what you need for now, until we get WhileLoading working well. Basically the content needs to be rendered for ReactiveRecord to know to fetch and apply that data, so we need to do a show/hide instead of preventing it from rendering until the data is there.