re-rxjs / react-rxjs

React bindings for RxJS
https://react-rxjs.org
MIT License
550 stars 19 forks source link

Observable emitting error should not cause infinite loop on Subscribe #274

Closed bruceharris closed 2 years ago

bruceharris commented 2 years ago

Under certain circumstances, a <Subscribe> with a nested component that uses a hook returned from bind(), where the observable emits an error, causes an infinite loop.

In the code example below, executable here, uncommenting the throw() on line 6 results in an infinite loop with the error being swallowed. Per discussion with @voliva who investigated this further, it seems that if and only if all of these conditions apply:

  1. The bind doesn't have a default value
  2. The shared observable is not passed to a <Subscribe>
  3. The observable emits the error asynchronously
  4. The observable doesn't emit any value before emitting the error (promises can either emit a value or error)

then the error is swallowed, and the component retries getting the value again

import { defer } from "rxjs";
import { bind, Subscribe } from "@react-rxjs/core";

async function mockFetch() {
  console.log("mockFetch()");
  // throw new Error("ouch");
  return new Promise((resolve) =>
    setTimeout(() => {
      resolve(42);
    }, 1000)
  );
}

const [useSomeData] = bind(defer(mockFetch));

function SomeData() {
  const data = useSomeData();
  return <>{data}</>;
}
export default function App() {
  return (
    <Subscribe fallback="Loading...">
      <SomeData />
    </Subscribe>
  );
}
josepot commented 2 years ago

:wave: @bruceharris !

First and foremost: thanks a lot for taking the time to report this issue, and for providing a codesandbox along with an excellent explanation of the bug. :bow:

Fortunately, just a few minutes before you opened this issue we managed to merge a fix on #273 and we also published its patch on 0.9.8.

You can see in this codesandbox (based on yours) that the issue has now been fixed.

Once again, thanks for taking the time to report the issue! much, much appreciated!