Skip to content
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

while loading feature should use error boundries #70

Closed
catmando opened this issue Dec 5, 2018 · 3 comments
Closed

while loading feature should use error boundries #70

catmando opened this issue Dec 5, 2018 · 3 comments
Labels
enhancement New feature or request ready-to-release Internal Use Only: Has been fixed, specs passing and pushed to edge branch
Milestone

Comments

@catmando
Copy link
Contributor

catmando commented Dec 5, 2018

should also fix #67

@catmando
Copy link
Contributor Author

catmando commented Dec 5, 2018

Because this might be useful outside of hyper-model, move the whole thing into hyper-component with necessary hooks for hyper-model, rather than the core implementation being in hyper-model.

@catmando
Copy link
Contributor Author

catmando commented Dec 7, 2018

The component DSL changes have been implemented and a works like this:

  1. You include Hyperstack::Component::WhileLoading in your component. (If anybody has a better name let me know)
  2. This adds a react error boundary around the component that will re-rerender the component if the component (or any of its children) loads data.
  3. Two observable instance methods are provided to get the state of the system: resources_loaded? and resources_loading?
  4. The resource_loading/loaded state change is not propagated down the tree. So the innermost component that includes the WhileLoading module deals with state change, displays a fallback and outer components are not affected. I.e. it works like any other error propagation.

You use the resource_loading/loaded? methods along with other state to control what is being displayed. When the state of resource_loading/loaded? changes the component will be forced to rerender, and you can then display a fallback.

Here is an example using the Todo code:

class App < HyperComponent
  include Hyperstack::Router
  include Hyperstack::Component::WhileLoading

  def get_scope!(match)
    @previous_scope = @scope
    @scope = Todo.send(match.params[:scope])
  end

  SCOPES = %i[all active completed]
  VALID_ROUTES = "/:scope(#{SCOPES.join('|')})"

  render(SECTION, class: 'todo-app') do
    if resources_loaded?
      Header()
      Switch() do
        Route(App::VALID_ROUTES) { |match| Index(scope: get_scope!(match)) }
        Route('/') { Redirect('/all') }
      end
      Footer()
    elsif @previous_scope
      Header()
      Index(scope: @previous_scope)
      Footer(:loading)
    else
      Header(:loading)
    end
  end
end

When the component first renders resources_loaded? will be true so the full display will render. Just before the DOM is updated, however the fact that now the state of resources_loaded? has changed (because we are loading some Todos) triggers App to rerender.

Now resources_loaded? is false, so we check @previous_scope which is still nil (see the get_scope method) so we render just Header(:loading) which displays a spinner.

Sometime later the data will be loaded, and so again this will trigger a rerender as resources_loaded? has again become true.

We now once again render the first block, and this time all data is loaded so no fall back occurs. Also the value of @previous_scope will be set to the current loaded scope.

Now if the user changes scopes, the cycle repeats. However this time when we execute the fallback @previous_scope has the value of the @scope before it was changed. So we use that to continue to render the current display while the loading happens in the background. We also set the loading tag on the Footer, which will show a loading spinner on the current link the user has pushed.

While this may seem complicated, its fairly intuitive and requires very little additional code to give a great user experience, and the code can be added after the fact, and is limited to just the component that will handle the fall back.

What the user sees on page load is a spinner while the data loads. There is no "flashing" or rerendering. Then once the data appears it immediately replaces the spinner. Then when the user clicks on a link to another route/scope, that link has a spinner, and the rest of the display stays as is, until the data is available, then immediately changes to the new scope.

@catmando catmando added this to the alpha1.3 milestone Dec 7, 2018
@catmando
Copy link
Contributor Author

closed in 242d7a9
see batch7/while_loading_spec.rb for examples

@catmando catmando added enhancement New feature or request ready-to-release Internal Use Only: Has been fixed, specs passing and pushed to edge branch labels Jan 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request ready-to-release Internal Use Only: Has been fixed, specs passing and pushed to edge branch
Projects
None yet
Development

No branches or pull requests

1 participant