Skip to content

Errors thrown in useEffect are not being caught #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
SachinSharmaE opened this issue Mar 4, 2020 · 6 comments
Closed

Errors thrown in useEffect are not being caught #305

SachinSharmaE opened this issue Mar 4, 2020 · 6 comments
Labels
enhancement New feature or request

Comments

@SachinSharmaE
Copy link

How to catch an throw Error which is thrown at first render ? for example

import React, { useState, useContext, useCallback } from 'react'

export function useCounter(initialValue = 0) {
  const [count, setCount] = useState(initialValue)

  React.useEffect(()=>{
  if (count > 100) {
    throw Error("It's over 100!")
  },[count])


  return { count}
}

and then i call the following code

import { renderHook, act } from '@testing-library/react-hooks'
import { useCounter } from './counter'

it('should throw when over 100', () => {
  const { result } = renderHook(() => useCounter(101))


  expect(result.error).toEqual(Error("It's over 100!"))
})

So how to catch an error that is thrown automatically on first render?

@SachinSharmaE SachinSharmaE added the question Further information is requested label Mar 4, 2020
@mpeyper mpeyper added bug Something isn't working and removed question Further information is requested labels Mar 4, 2020
@mpeyper mpeyper changed the title How to catch error on first render Errors thrown in useEffect are not being caught Mar 4, 2020
@mpeyper
Copy link
Member

mpeyper commented Mar 4, 2020

I took a look at this and it appears as though any errors being thrown in an effect (but not asynchronously) are not getting caught by the error handling in the test component.

A quick test showed that using an actual error boundary does catch this error so we could look into that to support this (and we should support this). Funnily enough, we used to have an error boundary but I removed it because of #50 and #74.

@SachinSharmaE
Copy link
Author

but is it a bug or an enhancement?
Also is there any solution for this as of now? even hacky way would work

@mpeyper
Copy link
Member

mpeyper commented Mar 5, 2020

I feel like it is a bug, but you're right, it's probably technically an enhancement.

Does wrapping the renderHook call with a try/catch work?

Alternatively you should be able to use the wrapper option of renderHook to add in your own error boundary to intercept the error.

I'm on my phone right now, but I can make an example for you later if that helps?

@SachinSharmaE
Copy link
Author

Sure, i will be waiting

@mpeyper
Copy link
Member

mpeyper commented Mar 9, 2020

Here is an example using an error boundary:

it('should throw when over 100', () => {
  let caughtError = null
  class ErrorBoundary extends React.Component {
    constructor(props) {
      super(props)
      this.state = { hasError: false }
    }

    componentDidCatch(error) {
      this.setState({ hasError: true })
      caughtError = error
    }

    render() {
      return !this.state.hasError && this.props.children
    }
  }

  const wrapper = ({ children }) => <ErrorBoundary>{children}</ErrorBoundary>

  renderHook(() => useCounter(101), { wrapper })

  expect(caughtError).toEqual(Error("It's over 100!"))
})

The following examples both rely on the error being raised out of the renderHook function to be caught:

it('should throw when over 100', () => {
  let caughtError = null

  try {
    renderHook(() => useCounter(101))
  } catch (error) {
    caughtError = error
  }

  expect(caughtError).toEqual(Error("It's over 100!"))
})
it('should throw when over 100', () => {
  expect(() => renderHook(() => useCounter(101))).toThrow(Error("It's over 100!"))
})

I'll let you decide which approach works best for your situation.

I've thought about it a bit more, and when a fix for this goes out, I will treat it as an enhancement and breaking change so that anyone relying on this behaviour for the workaround wont suddenly find they have breaking tests because the error it no longer being raised.

@mpeyper mpeyper added enhancement New feature or request and removed bug Something isn't working labels Mar 9, 2020
@SachinSharmaE
Copy link
Author

@mpeyper - thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants