Skip to content
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

fix(cache): remove previous data or error on new run #66

Merged
merged 2 commits into from
Sep 23, 2022

Conversation

PixnBits
Copy link
Contributor

@PixnBits PixnBits commented Sep 22, 2022

Description

If there is now data, remove the error from the previous run.
If there is now an error, remove the data from the previous run.

Motivation and Context

Sometimes there might be network issues (ex: traveling into a tunnel so the network disconnects) and a retry is desirable. As an example, a manual retry could be:

function BookList({ genre }) {
  const { isLoading, data, error, run } = useFetchye(`https://example.com/api/books/?genre=${genre}`;

  if (isLoading) {
    return (<p>Loading...</p>);
  }
  
  if (error || !data?.ok) {
    return (
      <>
        <p>Error encountered when loading the books</p>
        {error && <pre>{error.message}</pre>}
        <button type="button" onClick={run}>
          Retry
        </button>
      </>
    );
  }

  return (
    <>
      <p>Books!<p>
      <pre>{JSON.stringify(data.body, null, 2)}</pre>
    </>
  );
}

Currently, if there was an error the first load attempt error has a value (and data does not). However, on the second attempt if the request does go through and data now has a value error still has a value, persisted from the first attempt.

We can add an automatic retry to hit another scenario:

  // retry loading after five seconds when we don't have a usable response
  useEffect(() => {
    if (isLoading || data?.ok) {
      return;
    }
    const timeoutHandle = setTimeout(run, 5_000);
    return () => clearTimeout(timeoutHandle);
  }, [isLoading, data, error, run]);

If the first attempt is successful and data has a value (and error does not), but on the second attempt there is an error then error now has a value but data still has a value, persisted from the first attempt.

Additionally, with both entries having values it is difficult which of data or error are more recent. This is probably not too much of a concern for idempotent calls (e.g. GET) but this may cause challenges for mutating/non-idempotent calls (e.g. POST).

How Has This Been Tested?

Tests, keeping with their context, have been added. When generating snapshots Jest noted that it could not find Prettier, likely after the eslint configuration update; I installed Prettier locally to generate the inline snapshots but another PR will be needed to avoid this in the future.

Types of Changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation (adding or updating documentation)
  • Dependency update

Checklist:

  • My change requires a change to the documentation and I have updated the documentation accordingly.
  • My changes are in sync with the code style of this project.
  • There aren't any other open Pull Requests for the same issue/update.
  • These changes should be applied to a maintenance branch.
  • I have added the Apache 2.0 license header to any new files created.

What is the Impact to Developers Using Fetchye?

Some developers might be, perhaps unknowingly, relying on the current behavior. Generally though I see the current behavior as a bug especially due to the challenge of knowing which of data or error are most recent. If a component wishes to use the last available data before errors were encountered their best course of action is probably adding their logic needed using useState and useEffect, e.g.:

const [lastKnownData, setLastKnownData] = useState(data);
  useEffect(() => {
    if (!data) {
      return;
    }
    setLastKnownData(data);
  }, [data]);

or, if response status is important

if (!data?.ok) {

or

if (data?.status !== 200) {

depending on their specific circumstances

if there is now data remove the error from the previous run
if there is now an error remove the data from the previous run
@codesandbox-ci
Copy link

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 743f3e0:

Sandbox Source
quick-install Configuration
fetchye-provider-install Configuration
fetchye-redux-provider-install Configuration
nextjs-fetchye-ssr Configuration

@10xLaCroixDrinker 10xLaCroixDrinker requested a review from a team September 22, 2022 23:01
@10xLaCroixDrinker 10xLaCroixDrinker merged commit f921ef3 into main Sep 23, 2022
@10xLaCroixDrinker 10xLaCroixDrinker deleted the fix/state-after-rerun branch September 23, 2022 14:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants