1

I am following the tutorial on reactjs.org and I am practicing catching error with Error Boundaries. I have write my own code similar to the tutorial's code but I found that the Boundary does not re-render the fallback UI. I am using version 16.8.6 of React. Here is my code:

ErrorBoundary.js :

import React from 'react'

export const ErrorContext = React.createContext({
   error: null,
   errorInfo: null,
   clickCount: 0,
   increment : () =>{},

})
export default class ErrorBoundary extends React.Component{
   constructor(props){
       super(props);
       this.increment = ()=>{
           this.setState(state => ({
               clickCount : state.clickCount + 1
           }))
       }//method to increment clickCount by 1 per click
       this.state = {
           error: null,
           errorInfo: null,
           clickCount: 0,
           increment: this.increment
       }

   }
   resetDefault(){//method to reset number of click to zero (fix error)
       this.setState({
           clickCount: 0,
           error: null,
           errorInfo: null
       })
   }
   componentDidCatch(error,errorInfo){

       this.setState({
           error: error,
           errorInfo: errorInfo
       })
       console.log(this.state.error)
   }
   render(){
       if(this.state.error){//fallback UI
           return(
               <div>
                   <h2>An error has occured!!</h2>
                   <details>
                       {this.state.error}
                       <br/>
                       {this.state.errorInfo}
                   </details>
                   <button onClick = {this.resetDefault.bind(this)}>Click here to fix error </button>
               </div>
           )
       }
       return(

               <ErrorContext.Provider value = {this.state}>
                   {this.props.children}
               </ErrorContext.Provider>

       )
   }

}

ErrorThrower :

import React from 'react'
import {ErrorContext} from './ErrorBoundary'
class ErrorThrower extends React.Component{
    static contextType = ErrorContext
    constructor(props){
        super(props);
    }


    render(){
       if(this.context.clickCount === 6) {
          throw new Error('ErrorOccured')
       }
           return(
               <div>
                   <h2>Number of click count : {this.context.clickCount}</h2>
                   <button onClick = {this.context.increment}>Click here !!!</button>
               </div>
           )

    }
}
export default ErrorThrower

App.js :

import React from 'react';
import ErrorBoundary from './components/ErrorBoundary'
import ErrorThrower from './components/ErrorThrower';

function App() {
  return (
    <div className="App">
       <ErrorBoundary>
           <ErrorThrower></ErrorThrower>
       </ErrorBoundary>
    </div>
  );
}

export default App;

Following the tutorial (you can find at this link : https://reactjs.org/docs/error-boundaries.html) I have created ErrorThrower component which render one header and one button. When I click on button more than 5 times, an error will be thrown and React will render the fallback UI to display error log. And I have added another feature that allow me to fix the error (set the click count to 0 ) when I click a button in the fallback UI. However when I run project React does not fallback the UI to display error, it prints out the error stacktrace like normal. In the componentDidCatch() method the console prints out null value and I think setState() does not work. Anyone can show me what I did wrong in the code ?

3 Answers3

2

Here's my situation: my error in rendering React component triggers the closest error boundary to render the fallback UI. But in a few seconds, the stack trace shows up and covers my fallback UI.

enter image description here

Answer: It's the error overlay in create-react-app which only works in development mode.

You can simply click the cross button at the top right corner to show your fallback UI.

Reference: Disable error overlay in development mode

HeLin
  • 381
  • 3
  • 6
0

According to the docs, you should use static getDerivedStateFromError if you want to render a fallback. componentDidCatch should only be used for logging the error.

   static getDerivedStateFromError(error, errorInfo) {
     return {
       error,
       errorInfo
     }
   }

   componentDidCatch(error,errorInfo){
     console.log(error)
   }

https://reactjs.org/docs/error-boundaries.html

helloitsjoe
  • 6,264
  • 3
  • 19
  • 32
  • Well I tried to use `getDerivedStateFromError` to render fallback UI instead and it worked. However React only display the fallback UI for a few seconds and then it display the error stacktrace like before. Can you explain me how this can happened ? – Quang Bình Đinh Jul 29 '19 at 02:12
  • I can't explain that, but maybe if you update your question with the new code it would help. – helloitsjoe Jul 29 '19 at 02:35
  • 1
    @QuangBìnhĐinh, are your rendering inside of `getDerivedStateFromError`? If so, don't. From the docs, there is this comment in that method, "`// Update state so the next render will show the fallback UI.`". This is to show that this method is only called in transition, updating the error state so your can use in the next render. You can see a `if (this.state.hasError)` check on the sample code's `render` method. – Dev Yego Nov 16 '20 at 08:18
0

it might be due to create-react-app's react-overlay-error tool which shows error over fallback UI from error boundary just close iframe with error and your fallback UI will be displayed