58

I have a simple component that acts as an error boundary in my React app, and which passes off any errors to a logging service.

It looks something like this:

export class CatchError extends React.PureComponent {
  state = {
    hasError: false
  }

  componentDidCatch(error, info) {
    this.props.log({ error, info })
    this.setState({ hasError: true })
  }

  render() {
    const child = typeof this.props.children === "function"
      ? this.props.children({ error: hasError })
      : children

    return React.cloneElement(child, { error: this.state.hasError })
  }
}

Is there a React hook equivalent to componentDidCatch so I can make this component a function and not a class?

So it might look something like this:

export function CatchError({ children, log }) {
  const [hasError, setHasError] = useState(false)
  const caught = useDidCatch()

  useEffect(() => {
    const [error, info] = caught
    log({ error, info })
    setHasError(true)
  }, [caught])

  const child = typeof children === "function"
    ? children({ error: hasError })
    : children

  return React.cloneElement(child, { error: hasError })
}
sdgluck
  • 24,894
  • 8
  • 75
  • 90

3 Answers3

56

There is not a React hook equivalent of componentDidCatch.

However, the React team plans to add one soon.

The React docs state:

There are no Hook equivalents to the uncommon getSnapshotBeforeUpdate and componentDidCatch lifecycles yet, but we plan to add them soon.

Read more: https://reactjs.org/docs/hooks-faq.html#do-hooks-cover-all-use-cases-for-classes

sdgluck
  • 24,894
  • 8
  • 75
  • 90
  • It says "but we plan to add them soon.", But it doesn't seem to be implemented yet. Do you know if there was any problem? – Yuwaz Mar 08 '21 at 05:40
  • 3
    "No specific time commitment. When we have a good API. :-) These should be fairly uncommon anyway" https://github.com/facebook/react/issues/19630#issuecomment-675390931 – makkBit Mar 08 '21 at 07:02
22

There is not any official hook for Error Boundaries(componentDidCatch) in react. but you can simply use try...catch to catch component errors like this:

function myComponent(...) {
  // Initialize state variables.
  // Initialize context variables.
  // Initialize custom hooks.
  // ...

  try {
    // Define internal functions.
    // Define internal variables.

    return (
      <SomeThing />
    )
  } catch (error) {
    // Catch internal functions, variables and return (jsx) errors.
    // You can also create a lib to log the error to an error reporting service
    // and use it here.
  }
}

The try...catch block is the Error Boundry here.

Limitation: when you use a hook like useEffect and you use some internal functions in it, you cannot put that internal function into try...catch(Error Boundary) block because you should define that function on top of useEffect hook (why?) and you shouldn't use useEffect conditionally (why?)!

  • https://codesandbox.io/s/react-example-u43gf?file=/src/index.tsx – jeiea Apr 27 '20 at 22:09
  • @jeiea This is not exactly what I said. you should use try...catch inside Bomb to catch errors (there isn't a service like error boundaries which you use once forever. you should use try...catch everywhere you want to catch errors and send it to an external service) – Amir Mohammad Moradi Apr 28 '20 at 19:14
  • 2
    This approach is actually discouraged explicitly in the official doc. https://reactjs.org/docs/error-boundaries.html – Mike Feltman May 28 '20 at 20:16
  • 1
    no, it is not @MikeFeltman. they said `try / catch is great but it only works for imperative code` and I also mentioned the limitations of this approach! – Amir Mohammad Moradi May 29 '20 at 11:17
  • "try / catch is great but it only works for imperative code ... However, React components are declarative and specify what should be rendered" – Mike Feltman May 29 '20 at 13:50
  • 3
    I understand the answer and use a similar technique in my code. It's not quite the same thing as componentDidCatch or creating an error boundary, but it is as close as we can get in a functional component right now. – Mike Feltman May 29 '20 at 19:54
  • 1
    @MikeFeltman Exactly! also as you see my answer to this question was `There is not any official hook for Error Boundaries(componentDidCatch) in react.` and the others was `to catch component errors`. I believe *-1* is unfair ;) – Amir Mohammad Moradi May 31 '20 at 11:57
4

As mentioned already, the React team has not yet implemented a hook equivalent, and there are no published timelines for a hook implementation.

A few third party packages on npm implement error boundary hooks. This is the most popular npm package. Alternatively, I published react-use-error-boundary, attempting to recreate an API similar to useErrorBoundary from Preact.

Tate Thurston
  • 4,236
  • 1
  • 26
  • 22