Git Product home page Git Product logo

use-abortable-fetch's People

Contributors

aaronshaf avatar dependabot-preview[bot] avatar dependabot[bot] avatar greenkeeper[bot] avatar mauricedb avatar mergify[bot] avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

use-abortable-fetch's Issues

An in-range update of @types/jest is breaking the build 🚨

The devDependency @types/jest was updated from 24.0.11 to 24.0.12.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/jest is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Refresh interval

What would be the easiest way to call this hook in an abortable and restartable loop every refreshInterval milliseconds?

Could this config option be added to the hook?

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on Greenkeeper branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please click the 'fix repo' button on account.greenkeeper.io.

Support for headers?

Hey there. Would love to use this but at the moment it doesn't look to support headers which would be needed for things like adding tokens to requests. Is that something you can see adding in? I am thinking axios-like functionality.

Using the hook twice in the same component appears to cause to other fetch to abort

When using the hook twice in the same component I've noticed occasions where one of the fetches is aborted when the other is completed.

Example code:

function useProductData(options) {
  const { data: filterData, loading: filterLoading, error: filterError } = useAbortableFetch(
    `/api/products/${options.cultureCode}/filters/${options.filters.categoryId}`,
  );

  const { data: productData, loading: productLoading, error: productError } = useAbortableFetch(
    `/api/products/${options.cultureCode}?${queryString.stringify(options.products)}`,
  );

  return {
    error: filterError || productError,
    filterData,
    loading: filterLoading || productLoading,
    productData,
  };
}

When removing one of the calls the other fetch works consistently.

Any way to make the TypeScript definition for `data` a little smarter?

We noticed you can supply a type, which then becomes used for data:

const { data } = useAbortableFetch<Foo>('/api/some-endpoint');

The combined type definition for what gets returned looks like:

interface AbortableFetchResult<T> = {
  data: T | string | null;
  error: Error | null;
  abort: () => void;
  loading: boolean;
};

It's a nice convenience; However, the issue with this is that it forces consumers to allow their typedefs to include string, or otherwise cast data:

if (data) {
  const somethingThatCanOnlyBeFoo: Foo = data; 
  // Error TS2322: Type 'string | Foo' is not assignable to `somethingThatCanOnlyBeFoo`
}
if (data) {
  const somethingThatCanOnlyBeFoo: Foo | string = data; 
  // Works here, but breaks later in places where 'string' is not allowed
}
if (data) {
  const somethingThatCanOnlyBeFoo: Foo = data as Foo; 
  // Works, but defeats any value of passing type to `useAbortableFetch`
}

I understand why string is an option (i.e. for the case of res.text()) - but it breaks for any consumers whose type definitions do NOT want to allow string.

I am not sure that there is a solution for this, because you want to support res.text() and TypeScript cannot assume that T includes the string type if it is needed:

let data: T | string | null = null; // MUST include string or TS will yell at rsp.text()

if (isJSON(contentTypeHeader)) {
  data = await rsp.json();
} else {
  data = await rsp.text();
}

But I wanted to bounce this by you to see if maybe you had an idea that I couldn't figure out that would serve the purpose.

Thanks!

Consider batching updates to prevent multiple renders

Context

Thanks for the very useful hook. We were going to build something similar using AbortController and found that you published something that suits our needs.

I have one request that I wanted to bounce off you to optimize the number of times the component lifecycle runs. React currently only batches state updates together inside event handlers (i.e. side-effects). When there are setState calls outside of event handlers (e.g. after an async fetch), the updates will not be batched. This results in multiple unnecessary renders.

In the case of use-abortable-fetch, the result is four renders, which could be reduced to two renders if the state updates were batched.

Example

Consider the following case:

const { data, loading, error } = useAbortableFetch('/api/some-endpoint');
console.log('data', data);
console.log('loading', loading);
console.log('error', error);
console.log('--------------------------');

This will result in the below output:

data null
loading false
error null
--------------------------
data null
loading true
error null
--------------------------
data {…}
loading true
error null
--------------------------
data {…}
loading false
error null
--------------------------

As you can see, a single fetch is represented by four unique states, that results in four renders:

  1. the initial non-loading null state
  2. the loading state
  3. the loading + data state
  4. the non-loading + data state

Potential solutions

Either of the below options would require some bit of refactoring, but would result in the optimal number of renders, and the ideal output for the above example:

data null
loading true
error null
--------------------------
data {…}           <--- or data will be null if error is set
loading false
error null
--------------------------

Option 1 [recommended] - refactor to minimize the number of calls to setState

Instead of updating the state 3x, only update it 1x (when the fetch completes / fails).

If you return the default state with loading=true (instead of setting it in useEffect), then you can combine renders 1 & 2. Then, if you update the data={} & loading=false states at once, then you can combine renders 3 and 4.

Renders 3 and 4 are already combined in the error case

Option 2 - unstable_batchedUpdates

There exists a temporary API to force batching. If you wrap the setState calls in ReactDOM.unstable_batchedUpdates, then multiple calls will be batched.

This option still requires some refactoring, because all of the setState calls would need to be in the same batchedUpdates(() => {}) callback for it to function correctly.

The react team expects to remove this API in the future and instead batch everything by default.

More info
@see facebook/react#14259

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.