Errors in render() persist even after removing component
See original GitHub issueI reproduced this with a simple example (source code below) <App> is the parent component, <Profile> is the child
- Clicking the button in Profile sets state.error to true which successfully renders the error page.
- If instead I cause a TypeError in Profile (a plausible runtime occurrence if an object property is null), the error page does not show, even though state.error is still set to true.
e.g. change to
<div class={style.profile.x.y}>
in Profile - If I repeat 2) but set default state.error to true (so that Profile is never rendered) the error page successfully renders.
The difference between 2) and 3) suggests there might be an issue replacing a component that rendered with an error.
app.js
import { h, Component } from 'preact';
import Profile from './profile';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
error: true
};
window.onerror = () => {
this.setState({
error: false
});
};
}
throwError = e => {
throw new Error('error generated');
};
render() {
console.log('this.state.error', this.state.error);
return (
<div id="app">
{this.state.error ?
<div>{'error, please refresh'}</div> :
<Profile throwError={this.throwError}/>
}
</div>
);
}
}
profile.js
import { h, Component } from 'preact';
import style from './style';
export default class Profile extends Component {
render({throwError}) {
return (
<div class={style.profile}>
<h1>Profile.</h1>
<p>This is the profile page</p>
<button onclick={throwError}>{'Throw Error'}</button>
</div>
);
}
}
Issue Analytics
- State:
- Created 7 years ago
- Reactions:2
- Comments:10 (4 by maintainers)
Top Results From Across the Web
Errors in render() persist even after removing component #531
An exception encountered during rendering (essentially, within render() or a PFC) halts rendering but leaves pending renders queued. The next ...
Read more >A React component suspended while rendering, but no ...
It was using <Suspense /> element in the component but I removed it. Then application is crashed with above error.
Read more >5 Ways to Avoid React Component Re-Renderings
1. Memoization using useMemo() and UseCallback() Hooks. Memoization enables your code to re-render components only if there's a change in the props. With...
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 >How to solve too many re-renders error in ReactJS?
“Too many re-renderers” is a React error that happens after you have reached an infinite render loop, typically caused by code that in...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Wrote a wrapper based on yours (and then conditionally don’t render child components when in error state). It seems to be working well but feedback welcome.
Thanks again for your help!
An exception encountered during rendering (essentially, within
render()
or a PFC) halts rendering but leaves pending renders queued. The next setState() call will attempt to re-render the broken components.Philosophically, what could Preact do here? The child component cannot be rendered, since its render throws and thus has no return value. However, skipping its render would be a silent error.
FWIW I’ve actually used this behavior to implement error boundaries. Basically, you install a VNode hook that automatically wraps all component prototype methods in error softening via
console.error()
. A naive version looks something like this:Interestingly, because the behavior is entirely customizable via that hook, you could install a development error handler that intentionally blows up or
console.error()
's, but then switch to a production error handler that sequesters logging and attempts to continue rendering if possible to avoid white-screening.That brings me to the crux of the issue though: if a component errors, I’m not sure that there is a great way to recover or roll back. Any way you go about it, an error is going to produce incorrect UI state that was not expected.
Just my thoughts, I had been working on something like this over the past little while so it’s fresh in my brain. Happy you raised the issue here, maybe we can come up with a great open-source solution (either within preact or as a library).