fable-compiler / fable-react

Fable bindings and helpers for React and React Native
MIT License
275 stars 66 forks source link

React Error Boundary returns blank page on exception, instead of designated error component #163

Closed SpaceAntelope closed 5 years ago

SpaceAntelope commented 5 years ago

Hello and compliments for all the excellent work in this repository!

I am having some trouble using the provided react boundary class for fable. When attempting to throw an arbitrary exception in the view function (i.e. for testing the error component) instead of the error view I only see the white screen.

To cause an error, I use failwith in a header's child collection in the main view function:

Heading.h3 [] [
      str ("Press buttons to manipulate counter: " + show model) 
      str ( if model.Counter.Value.Value = 45 
            then failwith "This is a bug" else "") ]
|> ReactErrorBoundary.renderCatchSimple(errorComponent model dispatch)

The error component:

let errorComponent (model:Model) _ = 
        Browser.Dom.console.info("Error component with",model);
        div [] [ str "Rendering error" ]

The result is that the console.info message is shown twice, while the UI reverts to the white screen of death.

image

Here is an example project created with SAFE.Template 1.6 and one created with 1.0.0 which uses Fable2/React4. The template code is untouched, except for the additions noted above and the inclusion of the ReactErrorBoundary module in its own file.

When the UI appears, press + a few times and you will get an exception when reaching 45, as detailed above.

Here's hoping I'm just missing something obvious.

alfonsogarciacaro commented 5 years ago

Hi @SpaceAntelope, thanks for your words and the report! Hmm, to be honest I haven't used the ErrorBoundary myself. I assume you're following this guide that was contributed by @matthid. Maybe he can help here?

matthid commented 5 years ago

well it works for us last time I checked. Im curious why your code even compiles given that you use a 'ReactElement list' instead of a single 'ReactElement'

matthid commented 5 years ago

@alfonsogarciacaro Could it be that the latest Fable.Core 3 updates and something in the React binding changed and broke it? We don't use them yet...

SpaceAntelope commented 5 years ago

well it works for us last time I checked. Im curious why your code even compiles given that you use a 'ReactElement list' instead of a single 'ReactElement'

Hello @matthid, many thanks for replying. I could do with a working example, they seem to be extremely scarce other than the example in the documentation.

As for ReactElement list vs ReactElement I think the part of the code I quoted is misleading in that regard, the relevant context was this:

Content.content 
   [ Content.Modifiers [ Modifier.TextAlignment (Screen.All, TextAlignment.Centered) ] ]
   [ Heading.h3 [] [ 
       str ("Press buttons to manipulate counter: " + show model) 
       str (if model.Counter.Value.Value = 45 then failwith "You have reached the forbidden number" else "")
   ] ]
   |> ReactErrorBoundary.renderCatchSimple(errorComponent model dispatch)             

I will update the OP and the example project to make it clearer.

@alfonsogarciacaro Could it be that the latest Fable.Core 3 updates and something in the React binding changed and broke it? We don't use them yet...

I did get it to work for a node missing error, which was an actual bug and the reason i found out about error boundaries, so if Core 3/React 5 is to blame then it isn't a complete deal breaker. I did not post that example as it is kind of complex a test case, it involves changing the page after embedding a twitter timeline.

I will redo the example project with an earlier version of the SAFE.Template and post the results.

matthid commented 5 years ago

@SpaceAntelope Ok I looked at it briefly: The problem is that in your example the exception actually happens before the ReactErrorBoundary is even created. ReactErrorBoundary is required to catch errors which happen later, after view has returned its results and React calls onRender which is not the case in your example. In your example you can just use try --- with to catch the exception.

SpaceAntelope commented 5 years ago

@matthid I see! So it seems in fact my issue is, how can I cause an arbitrary exception in order to test the error boundary?

matthid commented 5 years ago

What comes to mind is to write a custom component and overwrite onRendet or use unbox to add elements as childs which react is unable to render

matthid commented 5 years ago

Generally, this situation should never happen in properly typed code in fable. In my project we needed the boundary in oder to safe-guard against components written in typescript where it is much easier to get into these kind of issues

SpaceAntelope commented 5 years ago

This is actually very interesting to hear. It's exactly the sort of meta information that would be immensely helpful for fable users without serious React experience like myself, were it readily available without a mentor.

I'm closing the issue, @matthid, @alfonsogarciacaro you've been incredibly helpful, many thanks!