Thursday, 28 January 2021

Update not wrapped in act() with multiple fetch requests using SWR

I have a test where if /endpoint1 fails, an error message should be displayed. The test passes however I get the following error from React Testing Library:

Warning: An update to HomePage inside a test was not wrapped in act(...).

Here's the snipper for clarity. You can see I'm using SWR to send requests. I'm mocking requests using Mock Service Worker.

export default function App() {
  const { data: data1, error: error1 } = useSwr("/endpoint1")
  const { data: data2, error: error2 } = useSwr("/endpoint2")

  if (error1 || error2) {
    return <Error />
  }

  return <Success />
}

The error is present because /endpoint2 resolves after /endpoint1, causing the component to rerender. I believed that cancelling the second request once the first one errors would work. I made a wrapper around useSwr() that used AbortController() and exposed an cancel() function however the same error would occur with this snippet:

export default function App() {
  const { data: data1, error: error1, cancel: cancel1 } = useCancellableSwr(
    "/endpoint1"
  )
  const { data: data2, error: error2, cancel: cancel2 } = useCancellableSwr(
    "/endpoint2"
  )

  if (error1 || error2) {
    if (!data1 || !error1) cancel2()
    if (!data2 || !error2) cancel1()
    return <p>Error</p>
  }

  return <p>Success</p>
}

For some reason, even after cancelling one endpoint, it still resolves and causes a rerender. Am I missing something here? Thanks

Edit:

Here's the failing test:

  test("An error shows if unable to fetch /endpoint1", async () => {
    mockServer.use(
      rest.get("/endpoint1", (_, res, ctx) => res(ctx.status(500)))
    )

    mockServer.use(
      rest.get("/endpoint2", (_, res, ctx) => res(ctx.status(200)))
    )

    render(<App />)

    const error = await screen.findByText("Error")
    expect(error).toBeInTheDocument()
  })

And my custom fetcher function:

async function serverFetch(endpoint) {
  const response = await fetch("http://localhost:8080" + endpoint)
  
  const body = response.json()

  if (!response.ok) {
    throw  new Error("An error occurred while fetching the data.")
  }

  return body
}



from Update not wrapped in act() with multiple fetch requests using SWR

No comments:

Post a Comment