question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if youā€™re still stuck at the end, weā€™re happy to hop on a call to see how we can help out.

Swallowing a loadable error in an Error Boundary leads to an infinite loop

See original GitHub issue

šŸ› Bug Report (/feature request?)

If you swallow a loadable error in an error boundary and render the same tree again, loadable will try to load that chunk once more, possibly triggering the same error, and so on.

In dev, this can lead to an infinite loop, in prod builds React might unmount instead.

Context: Some lazy-loaded components are ā€œoptionalā€, so in our app we often just want to report that they failed loading in an error boundary, but let the users keep using the page.

To Reproduce

  1. Wrap app in an error boundary that still renders this.props.children after chunk errors.
  2. Provoke a chunk error, for example by blocking that JS-resource in the browser network tab.

Expected behavior

If a lazy loaded component has already failed loading once, I expect the default to be to not try again. Possibly there should be an API to configure number of retries?

Today you would have to wrap every single Loadable in itā€™s own error boundary that renders null on chunk errors, which is very verbose and cumbersome.

Link to repl or repo (highly encouraged)

This codesandbox works by default and because of how codesandbox works you canā€™t block the JS-resource, BUT, you can simulate a chunk error by removing the export default in LazyComponent.

https://codesandbox.io/s/loadable-components-error-handling-xh1nn

Note that in our real app, this same error happens regardless of why the chunk failed to load, so for example timeouts or blocking the resource will have the same result.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:6

github_iconTop GitHub Comments

1reaction
Ephemcommented, Jun 9, 2021

Iā€™m not quite sure I understand? ErrorComponent in your post links to the fallback-prop, but I thought that is only rendered during loading precisely because Loadable is stateless (besides the promise itself)? If it does render during error as well, I canā€™t see a way of having both a loading state and an error state without using error boundaries?

I can see how I could solve this ā€œoptional lazy loaded componentā€ case with wrapping each such loadable in itā€™s own ErrorBoundary that renders null on error though, so if thatā€™s the recommended solution Iā€™m totally fine with that even if itā€™s a bit clunky. šŸ˜„

Iā€™m currently using something like this as a workaround for this issue and #717 , though itā€™s a bit unstable since it relies on internals:

import * as React from 'react';
import loadableBase from '@loadable/component';

export default function loadable(
  loadableImportObject,
  { ErrorFallback, ...options } = {}
) {
  let memoizedError = false;
  // Danger: Relying on loadable internals here!
  const originalImportAsync = loadableImportObject.importAsync;

  loadableImportObject.importAsync = function enhancedImportAsync(...args) {
    if (memoizedError) {
      return Promise.resolve(function ErrorFallbackWrapper() {
        return ErrorFallback ? <ErrorFallback error={memoizedError} /> : null;
      });
    }

    return originalImportAsync(...args).catch((error) => {
      if (typeof error === 'string') {
        error = new Error(error);
      }

      if (typeof error === 'object') {
        error.isChunkError = true;
      }

      memoizedError = error;
      throw error;
    });
  };

  return loadableBase(loadableImportObject, {
    ...options,
    fallback: options.fallback ?? null,
  });
}
0reactions
stale[bot]commented, Aug 10, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Ruby infinite loop causes 100% cpu load - Stack Overflow
After some thinking and suggestions from user2246674 I managed to resolve the issue. It was not inside the threads, it was the main...
Read more >
Crash your favorite compiler - Code Golf Stack Exchange
This creates an infinite loop at compile time: A BEGIN code block is executed as soon as possible, that is, the moment it...
Read more >
Common .NET Software Errors and How to Fix Them - Stackify
We've aggregated the 50 top .NET software errors. It includes exceptions, broken data bindings, memory leaks, etc. Find solutions on ways toĀ ...
Read more >
Chapter 4, Concurrency Patterns in Go - O'Reilly
It's very common to create goroutines that loop infinitely until they're stopped. ... When it cannot continue its work due to an unrecoverable...
Read more >
ESP32-CAM Troubleshooting Guide: Most Common Problems ...
Camera init failed with error 0x20001 or similar; Brownout detector or Guru meditation error; Sketch too big error ā€“ Wrong partition scheme selected;...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found