question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Render appends instead of replaces when there's an unexpected error

See original GitHub issue

When your <Page/> component unexpectedly throws, you may want to render an <ErrorPage/> component. Right now render will append the <ErrorPage/>, rather than replace the <Page/>.

Minimal Example:

<!DOCTYPE html>
<html>
<head></head>
<body>
  <div id="duo"></div>
  <script type="module">
    import { h, render } from 'https://unpkg.com/preact@10.0.0/dist/preact.module.js'
    
    function Page() {
      return h('div', {}, ['A'])
    }
    
    function PageWithError() {
      return h('div', {}, ['A', h(C, {})])
    }
    
    
    function ErrorPage({ error }) {
      return h('div', {}, error.message)
    }
    
    const parent = document.getElementById("duo")
    render(h(Page, {}), parent)
    
    try {
      render(h(PageWithError, {}), parent)
    } catch(error) {
      render(h(ErrorPage, { error }), parent)
    }
  </script>
</body>
</html>

Output:

A
C is not defined

Expected Output:

render(component, containerNode, [replaceNode]) behaves the same way regardless of if a component threw or not.

C is not defined

Here’s an interactive fiddle: https://jsfiddle.net/fwd4ktsy/6/

replaceNode doesn’t seem to work

I’ve also tried a bunch of variations using the replaceNode argument in render(component, containerNode, [replaceNode]), unfortunately, while it fixes this problem I’m reporting here, I run into another problem where render removes the DOM nodes on the next render: https://jsfiddle.net/fwd4ktsy/7/

Hacky Solution

In the try-catch you can set parent.innerHTML = '' which fixes the problem.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <div id="duo"></div>
  <script type="module">
    import { h, render } from 'https://unpkg.com/preact@10.0.0/dist/preact.module.js'
    
    function Page() {
      return h('div', {}, ['A'])
    }
    
    function PageWithError() {
      return h('div', {}, ['A', h(C, {})])
    }
    
    
    function ErrorPage({ error }) {
      return h('div', {}, error.message)
    }
    
    const parent = document.getElementById("duo")
    render(h(Page, {}), parent)
    
    try {
      render(h(PageWithError, {}), parent)
    } catch(error) {
      parent.innerHTML = ''
      render(h(ErrorPage, { error }), parent)
    }
    
    setTimeout(function() {
    console.log('re-rendering')
      render(h(Page, {}), parent)
    }, 1000)

  </script>
</body>
</html>

Let me know if you need any more info!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
JoviDeCroockcommented, Oct 13, 2019

This is a top-level example, you have to handle the way you see fit. In a previous project we made a button available to ensure that the user would not be on the fialing route and this would forward to the error logging service

0reactions
matthewmuellercommented, Oct 13, 2019

@JoviDeCroock gotcha. I think that code would result in an infinite loop, since children is what would be throwing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

React render appending rather than replacing content
I have a contentEditable react component that updates based on various state changes. The state item contains the paragraphs within the textbox.
Read more >
React Components rendered twice — any way to fix this?
Let's find out if there is a way to avoid this problem by trying different implementations. A) Functional Component with useState. function App()...
Read more >
Render tool is overwriting output data files in same file
I have 3 output data and 1 render tool outputting in same excel ... or use the same method but using the output...
Read more >
Render #pre_render callbacks must be methods of a class ...
The change request says 'If the callback is a RenderElementInterface object no update is necessary'. The vertical tabs class implements that ...
Read more >
How to Upgrade to React 18
There is no one-to-one replacement for the old render callback API — it depends on your use case. See the working group post...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found