Recovering from Errors

The rescues lifecycle callbacks run when an error is raised from within or below a component.

At the end of the rescue the component tree will be completely re-rendered from scratch. In its simplest form we need nothing but an empty block.

class App < HyperComponent
  render(DIV) do
    H1 { "Welcome to Our App" }
    ContentWhichFailsSometimes()
  end

  rescues do
  end
end

When an error occurs it will be caught by the rescues block, and App and all lower components will be re-generated (not just re-rendered).

In most cases you may want to warn the user that something is going wrong, and also record some data about the event:

class App < HyperComponent
  render(DIV) do
    H1 { "Welcome to Our App" }
    if @failure_fall_back
      DIV { 'Whoops we had a little problem' }
      BUTTON { 'retry' }.on(:click) { mutate @failure_fall_back = false }
    else
      ContentWhichFailsSometimes()
    end
  end

  rescues do |err|
    @failure_fall_back = true
    ReportError.run(err: err)
  end
end

If you don't want to involve the user, then be careful: To prevent infinite loops the React engine will not rescue failures occurring during the re-generation of the component tree. If not involving the user you may want to consider how to insure that system state is completely reset in the rescue.

The rescues method can also take explicit Error types to be rescued:

  rescues StandardError, MyInternalError do |err|
    ...
  end

Like other lifecycle methods you can have multiple rescues in the same component:

  rescues StandardError do |err|
    # code for handling StandardError
  end
  rescues MyInternalError do |err|
    # different code for handling MyInternalError
  end

Like Ruby's rescue keyword, errors will be caught by the innermost component with a rescues callback that handles that error.

The data passed to the rescue handler is an array of two items, the Ruby error that was thrown, and details generated by the React engine.

  rescues do |e, info|
    # e is a Ruby error, and responds to backtrace, message, etc
    # info is a hash currently with the single key :componentStack
    # which is string representing the backtrace through the component
    # hierarchy
  end

Caveats

  1. You cannot rescue errors raised in lifecycle handlers in the same component. Errors raised by lifecycle handlers in inner components are fine, just not in the same component as the rescue.

  2. Errors raised in event handlers will neither stop the rendering cycle, nor will they be caught by a rescue callback.

Last updated